Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Java hjärnsläpp, classer

Hej!
jag har fått hjärnsläpp, antagligen ett ganska simpelt problem.
Det är som så att jag inne i en class vill öppna en ny class, men ta med mig de sparade variabelvärdena i MyClass, som ni ser är även MyClass beroende utav en annan class
public MyClass()
public MyClass(AnnanClass annanClass) {
this.annanClass = annanClass;
}

och har i den en funktion som ska öppna en ny class

public MyClass2(MyClass myClass)

och den classen tar som ni ser min första class som inparameter och första classen är beroende utav en annan class.

Den bästa lösningen jag kom på var att inne i MyClass skapa dem på nytt
AnnanClass annanClass = new AnnanClass();
MyClass myClass = new MyClass(annanClass);
MyClass2 myClass2 = new MyClass2(annanClass, myClass);

Men detta var verkligen inget bra eftersom att jag då upptäckte att jag tömde mina variabler som jag skulle vilja komma åt i MyClass2

Så nu skulle jag alltså vilja ha hjälp med hur jag kan göra detta på ett smart sätt så att mina variabler slipper tappa dess värden.

Trädvy Permalänk
Medlem
Plats
Bromma
Registrerad
Aug 2008

Lite svårförstådd fråga, men är det inte så att du vill ärva från annanclass?

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

Jag håller med KurreKula, det var lite svårt att förstå vad du menar. Vad är egentligen MyClass2 t.ex., är det en funktion eller klass? Du säger ju först att det är en funktion, men använder den sedan som en klass. Och vad menar du med att du vill öppna en ny klass? Menar du kanske att du vill skapa en ny instans av klassen?

Om du vill få någon vettig hjälp så får du nog försöka förklara vad det är du vill lite bättre. Kanske kan du också visa den riktiga koden, istället för några enstaka fragment.

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Jag förstår det och ska nu visa koden och försöka vara så tydlig som möjlig.
Det som händer är alltså att jag i controller när man klickat på button1 tilldelar variabeln x ett värde (hej), men när jag sen har klickat på button2 så är det null, jag vill alltså att det fortfarande ska vara hej då. Hoppas att jag har förklarat det tillräckligt tydligt då och att ni med hjälp av koden kan förstå vad jag menar. Och det är alltså detta jag behöver hjälp med, hur ska man lösa det så att värdet på variabeln x fortfarande är hej där och inte null.
view

package view; import java.util.Observable; import java.util.Observer; import javax.swing.JButton; import javax.swing.JFrame; import view.View; import controller.Controller; import model.Model; public class View extends JFrame implements Observer{ private Model model; private Controller controller; public View(Model model, Controller controller) { this.model = model; this.controller = controller; model.addObserver(this); JButton button1 = new JButton("Click here to open a new frame"); button1.addActionListener(controller); button1.setActionCommand("button1"); add(button1); setTitle("Testing testing"); setSize(300, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } public static void main(String[] args) { Model model = new Model(); Controller controller = new Controller(model); View view = new View(model, controller); view.setVisible(true); } public void update(Observable obs, Object arg) {} }

controller

package controller; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import view.NewFrame; import model.Model; public class Controller implements ActionListener{ private Model model; String x; public Controller(Model model) { this.model = model; } public void actionPerformed(ActionEvent e) { // if("button1".equals(e.getActionCommand())){ System.out.println("button1"); x = "hej"; model.openFrame(x); } else if("button2".equals(e.getActionCommand())){ System.out.println("button2 " + x); //När jag klickat här är x = null, jag vill att den fortfarande ska vara = hej } } }

model

package model; import java.util.Observable; import view.NewFrame; import controller.Controller; public class Model extends Observable{ public void openFrame(String x){ Model model = new Model(); Controller controller = new Controller(model); NewFrame newFrame = new NewFrame(model, controller, x); newFrame.setVisible(true); } }

newFrame

package view; import java.util.Observable; import java.util.Observer; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import model.Model; import controller.Controller; public class NewFrame extends JFrame implements Observer { private Model model; private Controller controller; public NewFrame(Model model, Controller controller, String x){ this.model = model; this.controller = controller; model.addObserver(this); JButton button2 = new JButton("Click here... AND?!"); button2.addActionListener(controller); button2.setActionCommand("button2"); add(button2); setSize(200,200); setTitle("Testing testing New Frame"); setLocationRelativeTo(null); } @Override public void update(Observable obs, Object arg) { } }

Trädvy Permalänk
Medlem
Plats
Bromma
Registrerad
Aug 2008

Flytta ut x till newframe?

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Du skapar en ny controller, vilket innebär att x för den instansen sätts till default, dvs null.

Är du säker på att du vill skapa en ny controller och model för din nya frame? Eftersom du har en event handler med hårdkodade if-satser i Controller så verkar det som att du egentligen vill använda en controller till att styra två views (vilket låter vettigt om alla views också använder samma model). En ny controller och model skapar du om det nya fönstret ska vara helt fristående från det förra vad gäller eventhantering och data.

Hursomhelst, om du är nöjd med din struktur ska du använda nyckelordet static. Din sträng definieras således private static String x

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Alltså, du har fått MVC-konceptet runt bakfoten. Model ska inte skapa en ny view, det är controllers jobb, eller möjligtvis din view. Variabeln x som du har bör däremot ligga i Model så att alla views som använder sig av den kan hämta samma data.

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Det är klart att jag vill ha det som det ska vara, försöker lära mig därav detta lite simpla exempel.
Jag vill alltså inte att det nya fönstret ska vara fristående från det andra fönstret men att skapa dem på nytt var det enda alternativet jag kom på. men kan du visa hur man kan göra utan att skapa dem på nytt eftersom att jag behöver dem till min nya class NewFrame.

fråga 2:
om jag istället skulle lägga öppning här i controller så skulle det vara korrekt?
Fast då utan att skapa dem på nytt.

controller

public void actionPerformed(ActionEvent e) { // if("button1".equals(e.getActionCommand())){ System.out.println("button1"); x = "hej"; Model model = new Model(); Controller controller = new Controller(model); NewFrame newFrame = new NewFrame(model, controller, x); newFrame.setVisible(true); }

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Nej, det skulle inte vara korrekt eftersom du tilldelar en ny model och controller till din nya view.

NewFrame newFrame = new NewFrame(this.model, this, x); newFrame.setVisible(true);

Om du använder den kodsnutten så skickar controllern referenser till sin modell och sig själv som argument. Detta innebär att newFrame får tillgång till dessa objekts existerande instansvariabler.

edit: läs lite här http://www.c2.com/cgi/wiki?ModelViewController
edit2: microsoft bjuder också på lite information http://msdn.microsoft.com/en-us/library/ms978748.aspx

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Tack så jättemycket!

Men dock över till en ny fråga jag har, denna handlar också om klasser så det kändes onödigt att skapa ett nytt ämne här på forumet för det.

Det är som så att jag har ett interface med lite olika grejer i, detta interface används sedan på en annan klass
Mitt interface ser ut såhär:

package meny; public interface MenuItem { public String getTitle(); public void execute(); }

Klasserna

package meny; public abstract class AbstractMenuItem implements MenuItem { private String title; public AbstractMenuItem(String title) { this.title = title; } public abstract void execute(); public String getTitle() { return title; } }

Säg att jag nu vill använda mig utav en klass nr2.

package meny; public abstract class AbstractMenuItem2 implements MenuItem { private String title; private String text; public AbstractMenuItem2(String title, String text) { this.title = title; this.text = text; } public abstract void execute(); public String getTitle() { return title; } public void setText(String text){ this.text = text; } public String getText(){ return text; } }

Som ni ser har jag ytterligare en sak i klass2 som inte finns i interfacet, hur ska jag göra för att kunna tilldela text ett värde i klass2?

Jag vill inte lägga till text i mitt interface för jag vill ha vissa gemensamma värden bara i interfacet. Och jag vill ha ett interface för jag vill kunna göra en lista över det som jag sen kan loopa igenom.
Men som sagt om man sen använder interfacet på x-antal klasser så blir det en hel del saker som skiljer sig mellan klasserna och jag vill inte att interfacet ska ta hand om mer än de gemensamma delarna och de specifika delarna för varje klass sköts i respektive klass.

Som i det här fallet vill jag att getTitle sköts av interfacet men eftersom text bara finns med i klass2 så vill jag att klass två tar hand om den variabeln

Trädvy Permalänk
Medlem
Plats
Karlskrona
Registrerad
Feb 2007

Har lite svårt att tolka vad du egentligen vill, men det verkar som att du missuppfattat lite vad ett Interface är.

Ett interface innehåller metoder som måste implementeras i klasserna som implementerar det.
Det vill säga att i ditt fall så måste GetTitle() och execute() implementeras i klasser som använder sig av Interface't MenuItem.

Om tanken istället är att du vill skapa en basklass och underklasser till detta, som har liknande funktionalitet/metoder men som skiljer sig på vissa aspekter så bör du kolla på arv och polymorfism.

Edit: för att ändra "text" i den nedersta av dina klasser så kan du t.ex. använda: SetText("en ny text");

AMD 1800X@Noctua NH-U12F | asus prime x370pro | MSI ARMOR 1070 8GB| 2x8GB Corsair Vengeance DDR4 3GHZ | NZXT H440 | CoolerMaster V850 | SSD 120GB+240GB*2 | DELL 2713HM | DELL 2209WA | Coolermaster quickfire | Razer Deathadder 2013.

Phenom X6 1045T | Corsair TWIN2X PC6400C4DHX 2x2GB + Crucial Ballistix Sport 2x2GB | Gigabyte ma785gmt-us2h | Silverstone Temjin 08 | Corsair VX450

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Med reservation för syntax error, run-time errors osv..

interface FooInterface { public void print(); } abstract class AbstractFoo implements FooInterface { protected String text = null; public void print() { System.out.println(text); } } class HelloFoo extends AbstractFoo { public HelloFoo() { this.text = "Hello World!"; } } class GoodbyeFoo extends AbstractFoo { public GoodbyeFoo() { this.text = "Farewell."; } public void sayHello() { System.out.println("I don't want to say hello!"); } }

Om vi nu tilldelar lite variabler med vårt interface..

FooInterface[] foo; ... foo[0] = new HelloFoo(); foo[1] = new GoodbyeFoo(); ...

Så kan vi naturligtvis köra

foo[0].print(); foo[1].print();

Vad vi inte kan göra är att köra

foo[1].sayHello() // metoden finns inte i interface

vad vi däremot kan göra är att casta objektet till rätt klass

GoodbyeFoo bar = (GoodbyeFoo) foo[1]; bar.sayHello();

Jag vet inte om detta är vad du är ute efter. Det borde fungera men jag har inte programmerat java på ett par år så det kommer med en stor fet brasklapp.

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

for(Objects object : layer.getObjects()) { if (object instanceof Rectangle) { Rectangle r = (Rectangle) object; r.setBorder(true); } }

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Tack så jättemycket du är verkligen vänlig som hjälper
Men om vi då knyter ann till det min fråga egentligen började med, flera views knutna till samma controller och model.

Om vi då i controllern har koden som du gav mig, det jag alltså vill är att kolla om r är har getBorder som true eller false, om den är true vill jag att checkboxen i min öppnade view properties ska vara ikryssad när man öppnar rutan samt visa textboxen men hur gör man för att kryssa i den?

controller

public void itemStateChanged(ItemEvent e) { for(Objects object : layer.getObjects()) { if (object instanceof Rectangle) { Rectangle r = (Rectangle) object; if(r.getBorder()==false){ //sätt checkboxen Ej ikryssad } else{ //sätt checkboxen ikryssad } } } } //Men hur ska jag göra för JCheckBox cbBorder = null; Object source = e.getItemSelectable(); if (source == cbBorder) { }

I properties vill jag alltså att ska se lite olika ut beroende om checkboxen är ikryssad eller ej, och som standardutseende ska den bero på om r.getBorder() är true eller false

properties

package view; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.Observable; import java.util.Observer; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import model.Layer; import model.Model; import controller.Controller; public class Properties extends JFrame implements Observer { private Model model; private Controller controller; private JCheckBox cbBorder; public Properties(Model model, Controller controller){ this.model = model; this.controller = controller; model.addObserver(this); setTitle("Properties"); setLocationRelativeTo(null); } public void rectangle(Layer layer){ // System.out.println("ObjectSettings " + layer); GridBagLayout m = new GridBagLayout(); setLayout(m); GridBagConstraints con; //Label JLabel dl = new JLabel("Properties for your " + layer.getType(), JLabel.CENTER); con = new GridBagConstraints(); con.gridwidth = 2; //Upptar två kolumner con.fill = GridBagConstraints.HORIZONTAL; //fyll ut båda con.gridy = 0; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl, con); add(dl); //Checkbox, i kryssad eller ej beroende på om r.getBorder() är true eller false cbBorder = new JCheckBox("Border"); cbBorder.addActionListener(controller); cbBorder.setActionCommand("cbBorder"); con.gridwidth = 2; //Upptar två kolumner con.fill = GridBagConstraints.HORIZONTAL; //fyll ut båda con.gridy = 1; con.gridx = 0; //rad och kolumn m.setConstraints(cbBorder, con); add(cbBorder); //Label visa endast om checkboxen cbBorder är ikryssad JLabel dl2 = new JLabel("Fil2: ", JLabel.RIGHT); con = new GridBagConstraints(); con.gridy = 2; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl2, con); add(dl2); //Label visa endast om checkboxen cbBorder är ikryssad JTextField dt2 = new JTextField(15); con.gridy = 2; con.gridx = 1; //rad och kolumn m.setConstraints(dt2, con); add(dt2); //Buttons JButton btnPropSave = new JButton("Save"); JButton btnPropCancel = new JButton("Cancel"); con = new GridBagConstraints(); con.gridy = 3; con.gridx = 0; // rad och kolumn con.ipadx = 5; //förstora knapparna före och efter texterna con.anchor = GridBagConstraints.EAST; //Högerjustera m.setConstraints(btnPropSave, con); add(btnPropSave); con.gridy = 3; con.gridx = 1; // rad och kolumn con.anchor = GridBagConstraints.WEST; //Vänsterjustera m.setConstraints(btnPropCancel, con); add(btnPropCancel); pack(); btnPropSave.addActionListener(controller); btnPropSave.setActionCommand("btnPropSave"); btnPropCancel.addActionListener(controller); btnPropCancel.setActionCommand("btnPropCancel"); } public void circle(Layer layer){ //Label JLabel dl = new JLabel(layer.getType(), JLabel.RIGHT); add(dl); pack(); } @Override public void update(Observable arg0, Object arg1) { // TODO Auto-generated method stub cbBorder.setSelected(true);//sätt den som ikryssad } }

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Att tänka utanför sina egna programmeringsproblem är uppfriskande och lärorikt har jag märkt. Förhoppningsvis lär vi oss bägge något i slutänden

Till frågan: Jag är inte helt säker på att jag hänger med i vad du är ute efter. Flödet för att kolla ifall checkbox är satt beror lite på hur du har implementerat MVC, men vad som är säkert är att dess tillstånd ska ligga i model om det är något som ska reflekteras på andra ställen i applikationen. Exempelvis om du vill att en checkbox i en frame ska bestämma om en label är synlig i en annan frame eller panel knuten till samma model..

Det finns inget "korrekt" sätt att definiera informationsflödet i MVC på. Man kan exempelvis göra en implementering enligt Observer-mönstret som du själv verkar vara inne på (fast du verkar inte implementera några Observer-metoder), eller så skippar man det och låter Controller ta hand om all trafik mellan Model och View. Vad som däremot är skrivet i sten är "bokstävernas" specifika uppgift, och ju tightare man spänner åt desto klarare blir implementeringen.

Hursomhelst, förenklat flöde för din checkbox:

1. checkbox kryssas för i View;
2. actionListener i Controller triggas genom #1. Controller säger åt Model att uppdatera sig enligt det nya värdet;
3. Model sätter nytt värde och säger till alla Observers att nu har något hänt;
4. samtliga Views som är Observers till Model får notify (genom metoden update()). Även den View som triggade flödet får denna notify.
5. samtliga Views hämtar det uppdaterade värdet från Model.

edit: hittade mera läsmat: http://java.sun.com/developer/technicalArticles/javase/mvc/

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Jo så långt hade jag förstått, det var mer programmeringsmässigt hur man skulle lösa det.
Jag vill som sagt öppna en ny JFrame och hur den ser ut ska bero på vilka värden den har i model, så om jag då vill att dess utseende ska bero på exempelvis r.getBorder(), vart någonstans ska jag bestämma detta. Detta rör ju när jag precis har öppnat en ny view och inte hunnit ändra på något än så att en lyssnare hunnit registrera något jag själv tryckt på.

Och det var det jag försökte förklara med ovanstående kod.
properties är alltså den nya view som jag ska öppna, men är r.getBorder true så ska även checkboxen vara ikryssad.

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Hämta data från modellen när du öppnar den då.

class Properties .. { private Model model; // ... övriga deklarationer... public Properties(Model model) { this.model = model; } public void rectangle(Layer layer) { // ... cbBorder = new JCheckBox("Border"); boolean isCheckBoxSelected = model.getState('checkbox'); // eller hur du nu har implementerat det cbBorder.setSelected(isCheckBoxSelected); }

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Ja tack så mycket det löser en bit av problemet men inte riktigt allt, för meningen är att om checkboxen är ikryssad så ska följande kod visas, är den inte selected så ska den vara dold.

//Label visa endast om checkboxen cbBorder är ikryssad JLabel dl2 = new JLabel("Fil2: ", JLabel.RIGHT); con = new GridBagConstraints(); con.gridy = 2; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl2, con); add(dl2); //TextBox visa endast om checkboxen cbBorder är ikryssad JTextField dt2 = new JTextField(15); con.gridy = 2; con.gridx = 1; //rad och kolumn m.setConstraints(dt2, con); add(dt2);

Jag hade tänkt mig göra något liknande:
controller

model.setBorderSettingsVisible(true);

sen lägga en if-sats runt om det där i min view. är det ens meningen att man ska behöva lägga en if-sats i view? det känns inte som att det hör hemma där?
Så hur skulle man kunna lösa detta annars?

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007
Citat:

Ursprungligen inskrivet av mojito
... sen lägga en if-sats runt om det där i min view. är det ens meningen att man ska behöva lägga en if-sats i view? det känns inte som att det hör hemma där?
Så hur skulle man kunna lösa detta annars?

Det är ett sätt att lösa problemet på. Förslagsvis låter du metoden update() ta hand om det eftersom du har din Model/View som Observable/Observer.

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

hmm, jo men jag har inte till 100 förstått hur update(); fungerar tror jag
För nu tänkte jag att jag kunde använda mig utav samma boolean som jag tänkte förut men har nu istället flyttat ned koden till update();

Jag har förstått så mycket att update() reagerar på
setChanged();
notifyObservers(null);
från min model, men som det är ny händer ingenting så då tänkte att jag kunde skapa en updateView metod i min model som bara skulle uppdatera men detta fungerade inte.

Jag har även testat att lägga in den i min metoder som sätter om checkboxen ska vara markerad eller inte också men detta hjälpte inte heller utan får nullpointexp.. då

public void setCbBorderSettings(boolean cbBorderSettings){ this.cbBorderSettings = cbBorderSettings; setChanged(); notifyObservers(null); } public boolean getCbBorderSettings(){ return cbBorderSettings; }

public void update(Observable arg0, Object arg1) { // TODO Auto-generated method stub if(model.getCbBorderSettings()){ //Label JLabel dl2 = new JLabel("Fil2: ", JLabel.RIGHT); con = new GridBagConstraints(); con.gridy = 2; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl2, con); add(dl2); //Textfield JTextField dt2 = new JTextField(15); con.gridy = 2; con.gridx = 1; //rad och kolumn m.setConstraints(dt2, con); add(dt2); } }

Så hur ska man göra detta rätt?

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Du ska inte skapa dina labels i update(); gör du det kommer det skapas nya labels varje gång modellen uppdaterar sin data.

Bygg ditt GUI som vanligt och låt din view reagera på notify:es på lämpligt sätt, exempelvis genom att dölja de labels du önskar

class Model extends Observable { public static final String CHECKBOX_MSG = "checkbox"; public static final String FANCY_BUTTON_MSG = "fancybutton"; public static final String FOOGADGET_MSG = "foo"; // dessa används som "event-meddelande" // ... definitioner osv.. public void setCheckboxState(boolean state) { // om du har många olika fält i din model är det antagligen väldigt överflödigt att ha en metod för varje this.checkbox = state; this.setChanged(); this.notifyObservers(CHECKBOX_MSG); // ett objekt (i detta fall strängen "checkbox") skickas till samtliga Observers genom deras implementerade metod update() } // ... osv

class View implements Observer { // ... public void update(Observable source, Object code) { // här kollar vi ifall notifyn är intressant för oss if (code.equals(Model.CHECKBOX_MSG)) { // om vi fått ett checkbox-message av modellen... boolean state = model.getCheckboxState(); // hämta checkboxens värde från modellen. // OBS: detta hade man kunnat kolla redan i förra if-satsen. om man skulle ha fler modeller // kopplade till viewen så går det att få tag i rätt model genom att casta source. dl2.setVisisble(state); dt2.setVisible(state); // ... osv. Vill du reagera på flera events från model (vilket är troligt) kan du använda en switch-case istället för if. } } }

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

hmm, jag får Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException på

dl2.setVisible(state); dt2.setVisible(state);

det som jag har gjort är helt enkelt bara att sätta dem som false till början

//Textfield dt2 = new JTextField(15); con.gridy = 2; con.gridx = 1; //rad och kolumn dt2.setVisible(false); m.setConstraints(dt2, con); add(dt2);

det spelar heller ingen roll om jag sätter den som false till en början, den har nullpoint ändå, det spelar heller ingen roll om jag hårdkodar ett true i update()

dl2.setVisible(true); dt2.setVisible(true);

så vad kan det beror på att jag får nullpointexp där?

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Dom ligger i fel scope och är inte tillgängliga från update()

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006
Citat:

Ursprungligen inskrivet av Teknocide
Dom ligger i fel scope och är inte tillgängliga från update()

Vadå ligger i fel scope?
Jag har ju angett dem

private JLabel dl2; private JTextField dt2;

och då tycker åtminstone jag att jag borde kunna komma åt dem även i update() ?

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

I koden ovan har du i alla fall inte definierat dem utanför metod rectangle(...).
Om du har lagt till dem i efterhand så låter det som att du glömt ta bort den lokala variabeldeklarationen.

Det känns som att du gör precis samma misstag som jag brukar göra: vill förstå allting på en gång och börjar med att försöka implementera ett koncept jag inte förstått fullt ut. I slutänden sitter jag där med programkod som jag knappt kan läsa och inte orkar fixa iordning.

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006
Citat:

Ursprungligen inskrivet av Teknocide
I koden ovan har du i alla fall inte definierat dem utanför metod rectangle(...).
Om du har lagt till dem i efterhand så låter det som att du glömt ta bort den lokala variabeldeklarationen.

Jag hade bara lagt till dem som

private JLabel dl2; private JTextField dt2;

Men har nu istället satt dem till

private JLabel dl2 = new JLabel("Fil2: ", JLabel.RIGHT); private JTextField dt2 = new JTextField(15);

Då får jag inte längre ett felmeddelande men dock så händer det ingenting.
jag kommer in i update och går genom koden som jag ska men det händer inget, dl2 och dt2 blir inte visible för det. Hur kommer det sig?

dl2.setVisible(state); dt2.setVisible(state);

Jag har även kontrollerat så att state är true och även testat att hårdkoda in det.

Citat:

Ursprungligen inskrivet av Teknocide
Det känns som att du gör precis samma misstag som jag brukar göra: vill förstå allting på en gång och börjar med att försöka implementera ett koncept jag inte förstått fullt ut. I slutänden sitter jag där med programkod som jag knappt kan läsa och inte orkar fixa iordning.

Jo jag känner det också men tänkte försöka få koll på hur man använder update och göra det först, sen tänkte jag ta och börja om för att få bättre koll på men då har man en referens att lära sig ifrån vilket är kanon

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Ett litet exempel för att förklara var jag tror felet ligger:

class Properties { private JLabel dl2; private JTextField dt2; // här har du alltså definierat din label och textfield. dl2 == dt2 == null. // ... annat följer public void rectangle(Layer layer) { // ... stuff JLabel dl2 = new JLabel("Fil: ", JLabel.RIGHT); // Det är här det går fel: du skapar en lokal deklaration av dl2 vilket innebär att this.dl2 fortfarande är null. }

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Jo fast nu har jag alltså istället gjort

class Propertiess { private JLabel dl2 = new JLabel("Fil2: ", JLabel.RIGHT); private JTextField dt2 = new JTextField(15); public void rectangle(Layer layer) //Label con = new GridBagConstraints(); con.gridy = 2; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl2, con); dl2.setVisible(false); add(dl2); //Textfield con.gridy = 2; con.gridx = 1; //rad och kolumn dt2.setVisible(false); m.setConstraints(dt2, con); add(dt2); public void update(Observable arg0, Object arg1) { // TODO Auto-generated method stub if ("checkbox".equals(Model.CHECKBOX_MSG)) { // om vi fått ett checkbox-message av modellen... boolean state = model.getCbBorderSettings(); // hämta checkboxens värde från modellen. // OBS: detta hade man kunnat kolla redan i förra if-satsen. om man skulle ha fler modeller // kopplade till viewen så går det att få tag i rätt model genom att casta source. System.out.println("update " + state); dl2.setVisible(state); dt2.setVisible(state); // ... osv. Vill du reagera på flera events från model (vilket är troligt) kan du använda en switch-case istället för if. } } }

Vilket gör att jag slipper felmeddelandet med null, men dl2 och dt2 blir aldrig synliga även om jag sätter dem till visible nere i update

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

Har du kört rectangle någon gång? Annars har inte komponenterna lagts till i designen.

if ("checkbox".equals(Model.CHECKBOX_MSG))
Denna rad är tokig. Du kollar om en hårdkodad sträng ("checkbox") är detsamma som den statiska variabeln Model.CHECKBOX_MSG (vilket jag antar du satt till "checkbox" i modellen..). Och det kommer den ju alltid att vara. Din if-sats är effektivt sett "if (true) {...}"

Tanken är att du ska använda arg1 för att se vilken typ av förändring som skett i modellen. Det är troligt att du behöver casta den till String först, glömde det i mitt kodexempel ovan.

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2006

Ja rectangle har jag kört, den kör jag varje gång jag öppnar programmet.
Ja Model.CHECKBOX_MSG har jag satt till checkbox

Citat:

Ursprungligen inskrivet av Teknocide

Tanken är att du ska använda arg1 för att se vilken typ av förändring som skett i modellen. Det är troligt att du behöver casta den till String först, glömde det i mitt kodexempel ovan.

Med casta om den till string, är det då detta du menar?

if (arg1.toString().equals(Model.CHECKBOX_MSG)) {

för att underlätta kan jag lägga upp hela properties också:

package view; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.Observable; import java.util.Observer; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import model.Layer; import model.Model; import controller.Controller; public class Properties extends JFrame implements Observer { private Model model; private Controller controller; private JCheckBox cbBorder; private GridBagLayout m; private GridBagConstraints con; private JLabel dl2 = new JLabel("Fil2: ", JLabel.RIGHT); private JTextField dt2 = new JTextField(15); public Properties(Model model, Controller controller){ this.model = model; this.controller = controller; model.addObserver(this); setTitle("Properties"); setLocationRelativeTo(null); } public void rectangle(Layer layer){ // System.out.println("ObjectSettings " + layer); m = new GridBagLayout(); setLayout(m); //Label JLabel dl = new JLabel("Properties for your " + layer.getType(), JLabel.CENTER); con = new GridBagConstraints(); con.gridwidth = 2; //Upptar två kolumner con.fill = GridBagConstraints.HORIZONTAL; //fyll ut båda con.gridy = 0; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl, con); add(dl); //Border Checkbox cbBorder = new JCheckBox("Border"); cbBorder.addActionListener(controller); cbBorder.setActionCommand("cbBorder"); boolean isCheckBoxSelected = model.getCbBorderSettings(); cbBorder.setSelected(isCheckBoxSelected); con.gridwidth = 2; //Upptar två kolumner con.fill = GridBagConstraints.HORIZONTAL; //fyll ut båda con.gridy = 1; con.gridx = 0; //rad och kolumn m.setConstraints(cbBorder, con); add(cbBorder); //Label con = new GridBagConstraints(); con.gridy = 2; con.gridx = 0; //rad och kolumn con.insets = new Insets(10,0,10,0); //10 pixlar över och under m.setConstraints(dl2, con); dl2.setVisible(false); add(dl2); //Textfield con.gridy = 2; con.gridx = 1; //rad och kolumn dt2.setVisible(false); m.setConstraints(dt2, con); add(dt2); //Buttons JButton btnPropSave = new JButton("Save"); JButton btnPropCancel = new JButton("Cancel"); con = new GridBagConstraints(); con.gridy = 3; con.gridx = 0; // rad och kolumn con.ipadx = 5; //förstora knapparna före och efter texterna con.anchor = GridBagConstraints.EAST; //Högerjustera m.setConstraints(btnPropSave, con); add(btnPropSave); con.gridy = 3; con.gridx = 1; // rad och kolumn con.anchor = GridBagConstraints.WEST; //Vänsterjustera m.setConstraints(btnPropCancel, con); add(btnPropCancel); pack(); btnPropSave.addActionListener(controller); btnPropSave.setActionCommand("btnPropSave"); btnPropCancel.addActionListener(controller); btnPropCancel.setActionCommand("btnPropCancel"); } public void circle(Layer layer){ //Label JLabel dl = new JLabel(layer.getType(), JLabel.RIGHT); add(dl); pack(); } @Override public void update(Observable arg0, Object arg1) { // TODO Auto-generated method stub if (arg1.toString().equals(Model.CHECKBOX_MSG)) { // om vi fått ett checkbox-message av modellen... boolean state = model.getCbBorderSettings(); // hämta checkboxens värde från modellen. // OBS: detta hade man kunnat kolla redan i förra if-satsen. om man skulle ha fler modeller // kopplade till viewen så går det att få tag i rätt model genom att casta source. System.out.println("update " + state); dl2.setVisible(state); dt2.setVisible(state); // ... osv. Vill du reagera på flera events från model (vilket är troligt) kan du använda en switch-case istället för if. } } }

edit: det händer som sagt fortfarnde ingenting, därav att jag lade upp hela properties. För jag antar att det är i properties som det är något fel eftersom det är där jag sätter grejer till false och true. Jag kommer in i update() som sagt

Och om det nu inte skulle vara i properties så jag kan även visa hur jag öppnar den i controller:

properties = new Properties(this.model, this); //Vad är det för typ av object vi vill ändra properties för //Rectangle if(layer.getType()=="Rectangle"){ for(Objects object : layer.getObjects()) { if (object instanceof Rectangle) { Rectangle r = (Rectangle) object; if(r.getBorder()== true){ //sätt bordersettings ikryssat som default model.setCbBorderSettings(true); } else{ model.setCbBorderSettings(false); } } } //Gå in rectangle view samt visa fönstret properties.rectangle(layer); // rectangle.getBorder(); properties.setVisible(true); }