Java’da GUI’yi mantıktan ayırma

GUI'yi Java'daki program mantığının geri kalanından nasıl ayıracağımla ilgili pek çok makale ve (çok karmaşık) örnekler verdim ve tamamen dürüst olmak gerekirse, hala hiçbir fikrim yok.

Birisi bana bu basit örnekte, tek bir tuşla nasıl yapılacağına dair bir ipucu verebilir mi?

Diyelim ki Window sınıfında bir düğme var:

JButton firstButton = new JButton("My first button");      
btnCreateProject.setBounds(100, 100, 80, 30);
frame.getContentPane().add(firstButton);

diyelim ki bu düğme Employee sınıfının bir yapıcısını arayacak. Böylece, böyle yapabilirim:

JButton firstButton = new JButton("My first button");
firstButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
      .....constructor calling, and rest of the code....
   }
});
btnCreateProject.setBounds(100, 100, 80, 30);
frame.getContentPane().add(firstButton);

Ancak bu tam olarak ne yapmak istediğim değil. Window sınıfımın sadece saf GUI olmasını istiyorum, düğmeler, radyo kutuları ve diğer özelliklerle birlikte. Daha fazlası değil. Kontrolör diyelim ki tüm dinleyicileri başka bir sınıfta görmek istiyorum ve bu sınıftan gerekli tüm yöntemleri arayacağım.

Birisi bana bu basit düğme ile nasıl yapılacağına bir örnek verebilir misiniz? Çok teşekkür ederim.

2
Dinleyicinizi isimsiz bir iç sınıf olarak uygulamayın. Tam olarak söylediğin gibi yap. stackoverflow.com/a/4985539/2055998 gibi
katma yazar PM 77-1, kaynak
@TinoArts sadece açısalJS ile çalışmış olup olmadığını bilmek merak?
katma yazar Kick Buttowski, kaynak
Bir Swing uygulaması oluşturuyor gibisiniz, bu nedenle bu konu kaygıların uygun şekilde ayrılması hakkında fikir veriniz.
katma yazar Mick Mnemonic, kaynak
Ayrıca, katmanlı bir mimarinin önemli bir bileşeni bağımlılık enjeksiyonudur . Temel olarak bu, denetleyici/GUI sınıfınızdaki modelleri veya hizmetleri başlatmamanız gerektiği anlamına gelir.
katma yazar Mick Mnemonic, kaynak

6 cevap

Nazikçe değil dereceli bir ayrım yapıyorsunuz. GUI kodunuz program mantığından ayrı bir şekilde tamamen ayrılamaz, aksi takdirde modern sanatın statik bir eseri olur.

Çeşitli AWT/Swing dinleyici sınıfları, GUI'yi mantıktan tamamen ayrı sınıflara ayırır. Bununla birlikte, dinleyicileri anonim iç sınıflar olarak uygulamanıza gerek yoktur; belki de onları sıradan, en üst seviye sınıflar olarak uygulamak sizin için daha iyi olur. Alternatif olarak, Action arabirimini uygulayan sınıflar aracılığıyla program davranışlarını modellemenin size uygun olduğunu görebilirsiniz. Daha sonra bu davranışları kontrollere ' setAction() yöntemi ile kontrollere (düğmeler, menü öğeleri) atayabilirsiniz.

Bununla birlikte, herhangi bir şekilde GUI'nizi kuran kodun, bir şekilde hem GUI bileşenlerini hem de kendilerine bağlanması gereken mantığı bilmesi gerekir, aksi halde işini yapması mümkün değildir.

2
katma
Swing'i Java ile karıştırmayın
katma yazar notanormie, kaynak
@KickButtowski O var ama aynı zamanda sözde halefi olan ve MVC'yi daha iyi destekleyen JavaFX de var.
katma yazar notanormie, kaynak
Swing yerine @KickButtowski, JavaFX muhtemelen AngularJS ile daha karşılaştırılabilir . JavaFX, bildirimsel işaretleme (FXML üzerinden) ve ciltleme özellikleri için özellikler sağlar. afterburner.fx ile eşleştirilirse, bağımlılık enjeksiyonuna sahip bir MVP tarzı modeliniz olur. Yani, biraz açısal benzer, ama yine de farklı. Swing ve JavaFX, Oracle Java Runtime dağıtımının bir parçasıdır.
katma yazar jewelsea, kaynak
temelde Java, MVC tasarım desenini çok iyi desteklemiyor mu?
katma yazar Kick Buttowski, kaynak
@JohnBollinger hayır Ben zaten hiç için oy verdim müthiş cevabınızdaki hata bulmak istemedim. MVC'yi destekleyen açısal JS'leri inceliyorum ve cevabınız ile şu ana kadar öğrendiklerim arasında bazı bağlantılar buldum. Sadece daha iyi anlamaya çalışın hepsi bu :)
katma yazar Kick Buttowski, kaynak
@notanormie Her zaman Swing'in Java'nın bir parçası olduğunu düşündüm.
katma yazar Kick Buttowski, kaynak
sağolun beyler. JavaFX ile biraz çalıştım ancak bunun MVC veya MVP'yi desteklediğini bilmiyordum. Meydan okurcasına derinden bakarım.
katma yazar Kick Buttowski, kaynak
@KickButtowski, cevabımın böyle bir sonucu nasıl desteklediğini anlamıyorum. Bununla birlikte, hata bulmak istiyorsanız, genel olarak Java'yı değil, özellikle Swing'i seçiyor olmanız gerekir.
katma yazar John Bollinger, kaynak

Yapmanız gereken, datamodel'e erişmek için uygun bir yöntem yazmak (varsayalım) ve orada iş yapmak ve sadece düğmeyi tıklatarak yöntemi çağırmak.

firstButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
      logicClass.addEmployeeToFirm();
   }
});

veya olayı bu mantığı çağıracak/yapan özel bir Dinleyici yazabilirsiniz (ActionListener uygulayan bir sınıf).

0
katma
Daha da iyisi: SwingUtilites.invokeLater (new Runnable() {logicClass.addEmployeeToFirm ();})
katma yazar TameHog, kaynak
Bu yine de EDT iş parçacığında yapılacak. Ağır bir kaldırma olsaydı, EDT'de hiç yapılmamalıydı ama bence bu, bu sorunun odak noktası değil.
katma yazar notanormie, kaynak

Denetleyicinizin içinde bir yöntem oluşturun

Action get[Operation]Handler(); //Fill in [Operation] will what your button functionality should do

hangi uygun işlevselliği uygulayan bir iç sınıf döndürür.

Ardından, GUI kodunuzda

JButton b = ...;
b.setAction(controller.get[Operation]Handler());
0
katma
biraz daha açıklayabilir misin?
katma yazar Clark Kent, kaynak

Bu yeni bir sınıf için bir kurucu:

new ActionListener() {
   public void actionPerformed(ActionEvent e) {
      .....constructor calling, and rest of the code....
   }
}

Gibi bir sınıf yapabilirsiniz:

public class ActionListenerTest, ActionListener {'ı uygular ... }

O zaman şöyle bir şey yap:

firstButton.addActionListener(new ActionListenerTest());
0
katma

Projelerimde de aynı sorunu yaşadım, ancak nihayet android programlamada öğrendiğim bir konsepti kullanmaya karar verdim. İşte nasıl çalışıyor:

Nesnelerime bir tanım ekledim (düğmeler, menüler vb. İçin setActionCommand yöntemini kullanıyorum), böylece farklı bileşenler için aynı işlemler için aynı tanımlayıcıyı kullanabilirim.

Tüm nesnelerim, cmd olarak getActionCommand komutuyla ve nesnenin kendisiyle bir denetleyici çağırır. Kontrol ünitesinde cmd'yi kontrol ediyorum ve uygun yöntemi çağırıyorum.

GUI'yi ve programın geri kalanını kontrol etmek çok daha kolaydır.

Benim için cazibe gibi çalıştı.

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;

/**
 *
 * @author Pasban
 */
public class ActionListenerTest {

    public static void main(String[] args) {
        JButton b1 = new JButton("My first button");
        JButton b2 = new JButton("My first button");

        b1.setActionCommand("BTN_1");
        b2.setActionCommand("BTN_2");

        //put this in another class
        ActionListener controller = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String cmd = e.getActionCommand().toUpperCase().trim();
                System.out.println(cmd);

                //System.out.println(e.getSource());//cast to anything you have in your mind about the caller

                if (cmd.equals("BTN_1")) {
                    System.out.println("BUTTON 1 is clicked");
                } else if (cmd.equals("BTN_2")) {
                    System.out.println("BUTTON 2 is clicked");
                }
            }
        };

        b1.addActionListener(controller);
        b2.addActionListener(controller);

        JDialog frame = new JDialog();
        frame.setSize(new Dimension(300, 300));
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);


        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(b1);
        frame.getContentPane().add(b2);

        frame.setVisible(true);

    }
}
0
katma

Her zaman sadece şöyle bir şey uygulayabilirsiniz:

Controller.handleActionEvent(ActionEvent e);

ve düğmenizi delege etmek için buna tıklayın. Eğer kontrol cihazınızın Swing'i bilmesini istemiyorsanız, her zaman bir arayüz oluşturabilir ve Swing ActionEvent'i yaratmanızın bir tür etkinliğine sarabilirsiniz.

Ya da UI sınıfına sadece bir Gözlemci (Dinleyici) modeli uygulayın (ya da ortasında oturan bir "kayıt defteri" sınıfına sahip olabilirsiniz). Düğme tıklandığında, kullanıcı arayüzü olayı tüm kayıtlı dinleyicilere devreder (tanımladığınız bazı arayüzü uygular). Böylece Kontrolör (müşteri) UI’ye sadece “X Düğmesi tıklandığında beni haberdar et” diyecek ve UI ilgili tüm taraflara devredilecektir.

Bu nedenle, kullanıcı arayüzünün kimi açıkça arayacağını bilmesi gerekmez. Ancak kontrolör kimi dinlemek istediğini bilmek zorunda kalacaktır.

0
katma