Separera GUI och LOGIK i Java

Här diskuteras programmering och utveckling
TicToc
Inlägg: 2266
Blev medlem: 27 dec 2006, 17:28
OS: Kubuntu
Utgåva: 20.04 Focal Fossa LTS

Separera GUI och LOGIK i Java

Inlägg av TicToc »

Nu har jag börjat förstå värdet av att separera GUI från hanteringen av det logiska, men jag vet inte vilket av följande alternativ som är bäst, och kanske det finns ytterligare några som jag inte tänkt på. Språket är Java. Jag gick från Delphi till NetBeans GUI-builder och nu behöver jag lära mig att tänka i lite nya banor.

Alternativ 1:
Koppla varje unik händelse för ett unikt objekt i GUI:t till en egen funktion i logiken.

Alternativ 2:
Koppla alla händelser till en funktion i logiken som testar vad som hände, och sedan utför lämplig åtgärd.

Alternativ 3:
Koppla alla typer av händelser för en viss klass, exv, allt som har med meny att göra kopplas till logiken testgrupp för meny. Där testas det vilket händelse det var för vilket objekt. En annan grupp kan vara knappar.

Alternativ 4:
Koppla händelser av en viss typ exv, mousedown till logikens mousedown, alla mouseup till mouseup.

I min automatgenererade kod som jag för hand delat upp i GUI och LOGIK har jag fixat till så att följande används

Kod: Markera allt

        miHelpAbout.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _LOGIC_.menuAbout(evt);
            }
        });
miHelpAbout är en JMenuItem för menyn "Hjälp/Om".
Det kan utlösas av antingen F12, eller genom att menyn väljs.
Det verkar vara enligt Alternativ 1.

Jag tycker att det blir för kladdigt så här, har jag fel?
Rent spontat skulle jag föredra Alternativ 3.
Användarvisningsbild
micke_nordin
Inlägg: 1539
Blev medlem: 21 aug 2008, 17:03
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Separera GUI och LOGIK i Java

Inlägg av micke_nordin »

Jag förstår inte riktigt hur du menar, du måste ju koppla varje händelse i guiet till en lämplig funktion i den klass du vill anropa.

Exempelprogram: du har en klass "Search" som t.ex. kan söka i en sträng efter en annan sträng (som funktionen public boolean find(String keyword) tar som argument) och som sedan skickar en boolean som svar på om strängen fanns eller inte.

Du behöver då t.ex. ett JTextField där man kan skriva in sökord, textfältet kopplar du till ett privat fält i gui-klassen "SearchGUI". Sedan har du kanske en JButton som har en actionlistners som skickar nyckelordet till Search.find.

Exempelkod:

main

Kod: Markera allt

public class Main 
{

	public static void main (String args[]) 
	{		
		SearchGUI mGUI = new SearchGUI();
	}
}
search

Kod: Markera allt

import java.util.regex.Pattern;

public class Search 
{
	private String testString;
	
	public Search()
	{
		testString = "Detta är en teststräng";
	}
	
	public boolean find(String keyword)
	{
		return Pattern.matches(keyword, testString);
	}
	
	
}
SearchGUI

Kod: Markera allt

import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;


public class SearchGUI extends JFrame
{
	private static final long serialVersionUID = -3355859975236849718L; 
	private JTextField mTextField;
	public SearchGUI()
	{		
		super("My search app");
		JPanel mPanel = new JPanel();
		JButton mButton = new JButton("Search");
		mTextField = new JTextField("Regex here", 8);
		getContentPane().add(mPanel);

		mPanel.add(mTextField);
		mPanel.add(mButton);
		
		mTextField.addInputMethodListener(new InputMethodListener()
		{
			public void inputMethodTextChanged(InputMethodEvent event){}
			
			public void caretPositionChanged(InputMethodEvent event){}
			
		});
		
		mButton.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e)
			{
				Search mSearch = new Search();
				
				if(mSearch.find(mTextField.getText()))
				{
					JLabel yeah = new JLabel("Yeah");
					JFrame yeahFrame = new JFrame("Yeah");
					yeahFrame.add(yeah);
					yeahFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
					yeahFrame.setSize(150,50);
					yeahFrame.setVisible(true);
				}			

			}
		});
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(400,170);
		setVisible(true);		
	}
	
}

Jag tror att du skulle tjäna på att inte använda en gui-byggare utan i stället testa att handkoda ditt gui, det kan säkert klargöra en hel del.

/Micke
Användarvisningsbild
micke_nordin
Inlägg: 1539
Blev medlem: 21 aug 2008, 17:03
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Separera GUI och LOGIK i Java

Inlägg av micke_nordin »

Det kanske inte riktigt framgick vad jag menade, jag menar att du ju skall tänka objektorienterat runt hur du designar dina klasser, sedan kopplar du guiet på det sätt som är lämpligt utifrån hur du vill manipulera dina objekt.

/Micke
TicToc
Inlägg: 2266
Blev medlem: 27 dec 2006, 17:28
OS: Kubuntu
Utgåva: 20.04 Focal Fossa LTS

Re: Separera GUI och LOGIK i Java

Inlägg av TicToc »

Jag förstår inte riktigt hur du menar, du måste ju koppla varje händelse i guiet till en lämplig funktion i den klass du vill anropa.
Nja, det jag sett göras är att alla händelser kopplas till en funktion, och där reds det sedan ut vad som skall göras, anrop till lämplig funktion.

Tack för ditt exempel. Jag är också övertygad om att en uppdelning är rätt väg att gå.
Med ditt och andras exempel jag kikat på inser jag att uppdelningen kan ske på olika sätt.
Jag får skissa på lite olika upplägg och prova mig fram till vad som passar mig bäst, just nu.

Det jag kan se av ditt exempel är att det är centrerat runt guit, jag föredrar nog att låta en 'huvudlogikklass' vara i centrum, och innehålla ett objekt av klassen MittLillaGui. På så vis kan man även koppla ett textinterface till logiken. Klassen MittLillaGui innehåller objektet som utgör 'huvudlogikklassen', och anrop sker till den när saker skall utföras.

Så här har jag det nu, och fortsätter antagligen på det spåret med lite förfining.

Klassen Logik:

Kod: Markera allt

public abstract class Logik {
    public Gui gui;
    public Logik() {
        gui = new Gui(this);
    }
    protected void menuAbout(ActionEvent evt) {
        ...
    }
}
Klassen Gui:

Kod: Markera allt

public class Gui extends JFrame {
    private Logik logik;
    public Gui(Logik befintliglogik) {
            logik = befintliglogik;
    }
        miHelpAbout.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                logik.menuAbout(evt);
            }
        });
}
Detta funkar alltså idag, ser det supertokigt ut beror det på att jag har klippt och klistrat illa.

Då kanske jag är på rätt spår trots allt?
Användarvisningsbild
micke_nordin
Inlägg: 1539
Blev medlem: 21 aug 2008, 17:03
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Separera GUI och LOGIK i Java

Inlägg av micke_nordin »

TicToc skrev: Det jag kan se av ditt exempel är att det är centrerat runt guit
Mjo, det kanske blev så för att jag skrev ett exempel för att illustrera hur du kan tänka för att koppla guit till dina befintliga klasser. Det blev lite bakvänt med andra ord.

/Micke
TicToc
Inlägg: 2266
Blev medlem: 27 dec 2006, 17:28
OS: Kubuntu
Utgåva: 20.04 Focal Fossa LTS

Re: Separera GUI och LOGIK i Java

Inlägg av TicToc »

Det är lugnt, det hjälpte mig att tänka!
TicToc
Inlägg: 2266
Blev medlem: 27 dec 2006, 17:28
OS: Kubuntu
Utgåva: 20.04 Focal Fossa LTS

Re: Separera GUI och LOGIK i Java

Inlägg av TicToc »

Nu har jag valt en väg att gå, resultatet finns här: http://almond.svn.sourceforge.net/viewv ... iew=markup
Skriv svar

Återgå till "Programmering och webbdesign"