Avatar billede web_the_world Nybegynder
19. marts 2003 - 19:03 Der er 23 kommentarer og
1 løsning

Swing guru søges problem med tabbedpane

Jeg har et lille (stort) problem med mit porgram...

Jeg har lavet en main klasse med tabbedpane, som samler en masse i klasser til fanebladsprogram...Problemet er bare, at min klasse, som hedder Spm3 ligger sig henover de andre faneblade....Hvorfor gør den det og hvordan ændre man det?? Layoutet skal helst forblive på den måde som klassen Spm3 ser ud, men man skal jo helst kunne vælge de andre faneblade også

Koden er herunder - indsat to klasser (main og Spm3)

import java.sql.*;
import javax.swing.*;

public class TaxaBagger
{
static Connection con;
      public static void main(String[] args) throws Exception

  {

      //load driveren og opret en forbindelsesobjekt til taxa2
      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

      Connection con = DriverManager.getConnection("jdbc:odbc:taxa2");

      JFrame frame = new JFrame ("Layout Manager Demo");
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.setTitle("TAXA");     //titel på GUI
      JTabbedPane tp = new JTabbedPane();
      tp.addTab ("Oversigt", new IntroPanel());    //kalder de forskellige klasser
      tp.addTab ("Spm 3", new Spm3(con, frame));
      tp.addTab ("Spm 3b", new Spm3b(con));
      tp.addTab ("Spm 4", new Spm4(con));
      tp.addTab ("Spm 5", new Spm5(con));
      tp.addTab ("Spm 6", new Spm6(con));
      tp.addTab ("Spm 7", new Spm7(con));
      tp.addTab ("Spm 8", new Spm8(con));

      frame.getContentPane().add(tp);
      frame.pack();
      frame.show();
  }
}


klasse 2
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.sql.*;

public class Spm3 extends JPanel implements ActionListener
{
    private JFrame frame;
    private JPanel panelmain, panel1, panel2, panel3, panel4;

    private JButton søg, slut;    //trykknapper til hhv. at søge i databasen og afslutte
    private JTextField vognnr, dato;        //tekstfelter til hhv. vognnr og dato
    private JTextArea resultat;        //tekst felt til at udskrive resultat
    private int WIDTH = 210, HEIGHT = 170;
    private String resultatUd;
    private DataBase database;
    private Connection con;            //databaseforbindelses-objektet

    public Spm3(Connection con, JFrame fr)

    //konstruktør, sætter vinduet op
    {
        this.con= con;                    //overfør den modtagne databaseforbindelse

        database = new DataBase(con);

        frame = fr;


       
        setSize(80,180);                //sæt vinduets størrelse
        setLocation(100,100);            //og placering (målt i pixels)
        setLayout(new FlowLayout());    //vælg layoutmanageren 'FlowLayout'

        resultat = new JTextArea(10, 45);

        JLabel input1 = new JLabel("Indtast vognummer");    //skriv ledeteksten 'Vognnr'
        vognnr= new JTextField(10);
        vognnr.addActionListener(this); //definer og tilføj tekstfeltet vognnr


      JLabel input2 = new JLabel("Indtast dato");
        dato= new JTextField(10);
        dato.addActionListener(this);


        søg= new JButton("Søg");    //definer og tilføj søg-knappen

        søg.addActionListener(this);  //registrer søg-knappen, så tryk på
                                        //den kan opfanges

        slut= new JButton("Afslut");        //definer og tilføj slut-knappen

        slut.addActionListener(this);    //registrer slut-knappen, så tryk på den kan opfanges


        panelmain = new JPanel();
        panelmain.setLayout(new BoxLayout (panelmain, BoxLayout.Y_AXIS));


        //Panel til søg vognnr og dato
        panel1 = new JPanel();
        panel1. setLayout(new FlowLayout(FlowLayout.LEFT));
        panel1.setBorder(new javax.swing.border.TitledBorder("Spørgsmål 3"));

        //Panel til textArea
        panel2 = new JPanel();
        panel2. setLayout(new FlowLayout(FlowLayout.LEFT));
        panel2.setBorder(new javax.swing.border.TitledBorder("Resultat"));

        //Panel til afslut knap
        panel3 = new JPanel();
        panel3. setLayout(new FlowLayout(FlowLayout.LEFT));


        panel1.add(vognnr);
        panel1.add(new JLabel("Indtast Vognnr"));    //skriv ledeteksten 'Vognnr'
        panel1.add(dato);
        panel1.add(new JLabel("Indtast Dato"));
        panel1.add(søg);

        panel2.add(resultat);

        panel3.add(slut);

        panelmain.add(Box.createRigidArea(new Dimension(0,8)));
        panelmain.add(panel1);
        panelmain.add(Box.createRigidArea(new Dimension(0,8)));
        panelmain.add(panel2);
        panelmain.add(Box.createRigidArea(new Dimension(0,8)));
        panelmain.add(panel3);


        frame.getContentPane().add(panelmain);

        frame.pack();
        frame.show();
    }

    public void actionPerformed(ActionEvent e)
    //metode, der kaldes automatisk, når brugeren trykker på én af de registrerede
    //trykknapper (søg eller slut).
    {
        if (e.getSource() == vognnr || e.getSource() == dato || e.getSource() == søg)
        {
            try
            {
                resultatUd=database.udskrivspm3a(vognnr.getText(), dato.getText());
                resultat.setText(resultatUd);
            }
            catch(Exception ex){System.out.println(ex);}
        }
        else if (e.getSource()==slut)            //ellers hvis det var slut-knappen
        {
            try
            {
                con.close();                    //nedlæg forbindelsen til myDB
            }
            catch (Exception ex){System.out.println(ex);}
            System.exit(0);                            //afslut
        }
    }
}
Avatar billede viht Nybegynder
19. marts 2003 - 19:44 #1
Jeg har løst det, her kommmer den nye kode. Jeg har udkommenteret det jeg ikke har, men GUI funktionaliteten er den samme.

Jeg har tilføjet kommentarer hvor jeg har ændret noget!

// TaxaBagger.java:
import java.sql.*;
import javax.swing.*;
import java.awt.*;

public class TaxaBagger
{
static Connection con;
      public static void main(String[] args) throws Exception

  {

      //load driveren og opret en forbindelsesobjekt til taxa2
//      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

//      Connection con = DriverManager.getConnection("jdbc:odbc:taxa2");

      JFrame frame = new JFrame ("Layout Manager Demo");
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.setTitle("TAXA");    //titel på GUI
      JTabbedPane tp = new JTabbedPane();
//      tp.addTab ("Oversigt", new IntroPanel());    //kalder de forskellige klasser
      tp.add ("Spm 3", new Spm3(con, frame));
      tp.add("2", new JPanel());
//      tp.addTab ("Spm 3b", new Spm3b(con));
//      tp.addTab ("Spm 4", new Spm4(con));
//      tp.addTab ("Spm 5", new Spm5(con));
//      tp.addTab ("Spm 6", new Spm6(con));
//      tp.addTab ("Spm 7", new Spm7(con));
//      tp.addTab ("Spm 8", new Spm8(con));
        /**
        * Kommenteret ud, da jeg ikek har dem
        * "2", er bare et dummy panel for at testt
        */

      frame.getContentPane().add(tp, BorderLayout.CENTER);
      /**
        * Tilføjet BorderLayout.CENTER her, da dit JFrame bruger BorderLayout og du vil have JTabbedPane
        * ind midt i JFramet.
        */
      frame.pack();
      frame.show();
  }
}

// Spm3.java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.sql.*;

public class Spm3 extends JPanel implements ActionListener
{
    private JFrame frame;
    private JPanel panelmain, panel1, panel2, panel3, panel4;

    private JButton søg, slut;    //trykknapper til hhv. at søge i databasen og afslutte
    private JTextField vognnr, dato;        //tekstfelter til hhv. vognnr og dato
    private JTextArea resultat;        //tekst felt til at udskrive resultat
    private int WIDTH = 210, HEIGHT = 170;
    private String resultatUd;
//    private DataBase database;
//    private Connection con;            //databaseforbindelses-objektet

    public Spm3(Connection con, JFrame fr)

    //konstruktør, sætter vinduet op
    {
//        this.con= con;                    //overfør den modtagne databaseforbindelse

//        database = new DataBase(con);

        frame = fr;
        /**
          * Tilføjet BoxLayout til "this", som er et JPanel, du extender jo JPanel.
          */
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));    //vælg layoutmanageren 'FlowLayout'

        resultat = new JTextArea(10, 45);

        JLabel input1 = new JLabel("Indtast vognummer");    //skriv ledeteksten 'Vognnr'
        vognnr= new JTextField(10);
        vognnr.addActionListener(this); //definer og tilføj tekstfeltet vognnr


        JLabel input2 = new JLabel("Indtast dato");
        dato= new JTextField(10);
        dato.addActionListener(this);


        søg= new JButton("Søg");    //definer og tilføj søg-knappen

        søg.addActionListener(this);  //registrer søg-knappen, så tryk på
                                        //den kan opfanges

        slut= new JButton("Afslut");        //definer og tilføj slut-knappen

        slut.addActionListener(this);    //registrer slut-knappen, så tryk på den kan opfanges

        //Panel til søg vognnr og dato
        panel1 = new JPanel();
        panel1. setLayout(new FlowLayout(FlowLayout.LEFT));
        panel1.setBorder(new javax.swing.border.TitledBorder("Spørgsmål 3"));

        //Panel til textArea
        panel2 = new JPanel();
        panel2. setLayout(new FlowLayout(FlowLayout.LEFT));
        panel2.setBorder(new javax.swing.border.TitledBorder("Resultat"));

        //Panel til afslut knap
        panel3 = new JPanel();
        panel3. setLayout(new FlowLayout(FlowLayout.LEFT));


        panel1.add(vognnr);
        panel1.add(new JLabel("Indtast Vognnr"));    //skriv ledeteksten 'Vognnr'
        panel1.add(dato);
        panel1.add(new JLabel("Indtast Dato"));
        panel1.add(søg);
           
            /**
            * Tilføjet dit JTextArea til et JScrollPane, så det kan scrolle. Det er god kotume at gøre :)
            */
        panel2.add(new JScrollPane(resultat));

        panel3.add(slut);
           
          /**
          * Jeg har helt fjernet "mainpanel", da du bare kan bruge "this", som er et JPanel
          * du extender jo JPanel.
          * Jeg adder bare de tre komponenter på BoxLayoutet, og den lægger dem under hinanden.
          */
        add(panel1);
        add(panel2);
        add(panel3);
            /**
            * Dem skal du ikke kalde! Dit JFrame skal ikke kaldes fra andre steder. Når du "packer" det
            * bliver det lille, da alle komponenter krympes til min. størrelse.
            * Du skal heller ikke kalde show() herfra, du gør det allerede fra TaxaBagger.java
            */
//        frame.pack();
//        frame.show();
    }

    public void actionPerformed(ActionEvent e)
    //metode, der kaldes automatisk, når brugeren trykker på én af de registrerede
    //trykknapper (søg eller slut).
    {
//        if (e.getSource() == vognnr || e.getSource() == dato || e.getSource() == søg)
//        {
//            try
//            {
//                resultatUd=database.udskrivspm3a(vognnr.getText(), dato.getText());
//                resultat.setText(resultatUd);
//            }
//            catch(Exception ex){System.out.println(ex);}
//        }
//        else if (e.getSource()==slut)            //ellers hvis det var slut-knappen
//        {
//            try
//            {
//                con.close();                    //nedlæg forbindelsen til myDB
//            }
//            catch (Exception ex){System.out.println(ex);}
//            System.exit(0);                            //afslut
//        }
    }
}
Avatar billede viht Nybegynder
19. marts 2003 - 19:49 #2
Du bør også lige ændre følgende:
// nix: resultat = new JTextArea(10,45);
// gør i stedet: resultat = new JTextArea();

// nix: panel2. setLayout(new FlowLayout(FlowLayout.LEFT));
// gør i stedet: panel2.setLayout(new BorderLayout());

// nix: panel2.add(new JScrollPane(resultat));
// gør i stedet: panel2.add(new JScrollPane(resultat), BorderLayout.CENTER);
Avatar billede viht Nybegynder
19. marts 2003 - 19:52 #3
Det knusende problem var at du fra Spm3.java kaldte frame.getContentPane().add(panelMain); Hvilket resulterer i at du lægger dit JPanel ovenpå det JTabbedPane du lige har tilføjet. Du tilføjer jo allerede Spm3 panelet til JTabbedPane, så du skal til JFrame kun tiføjet JTabbadPane :)
Avatar billede web_the_world Nybegynder
19. marts 2003 - 19:55 #4
Det er perfekt..Nu håber jeg bare, at jeg kan finde ud af at gøre det med alle de andre klasser....tak for hjælpen

Hvorfor skal jeg lave de der ændringer - du skriver kl. 19:49:27 - hvad betyder de og hvad er forskellen?
Avatar billede viht Nybegynder
19. marts 2003 - 19:57 #5
Dette er ikke godt. Du giver JTextArea'et en fast størrelse. Så vil det ikke følge med LayoutManageren når du resizer framet.
// nix: resultat = new JTextArea(10,45);
// gør i stedet: resultat = new JTextArea();

Er bare det bedste Layout, når du kun har en komponent, der bare skal fylde hele panelet.
// nix: panel2. setLayout(new FlowLayout(FlowLayout.LEFT));
// gør i stedet: panel2.setLayout(new BorderLayout());

Fordi du i stedet tilføjer til et panel med BorderLayout, skal du angive hvor på panelet det skal tilføjes (WEST, NORTH, CENTER eller SOUTH)
// nix: panel2.add(new JScrollPane(resultat));
// gør i stedet: panel2.add(new JScrollPane(resultat), BorderLayout.CENTER);
Avatar billede r9 Nybegynder
19. marts 2003 - 19:57 #6
viht:

Hvordan er du blevet så forbandet hård til GUI?
Avatar billede viht Nybegynder
19. marts 2003 - 20:02 #7
Practise practise practise :)

Jeg har bare læst og prøvet og læst og prøvet.
Et er nemlig at lave GUI i Java, noget HELT andet er at lave god GUI i Java. Swing er bygget til at du kan designe helt vanvittigt gode brugergrænseflader, hvis du bruger det rigtigt og hvis du udnytter de designmønstre der ligger i det.

Jeg har gjort meget brug af APIen, og det gælder om at forsøge at lave tingene rigtigt fra start, så man ikke bliver for vant til at lave tingene forkert da det så bliver meget sværere at skifte.

Hver gang man skal afprøve en ny komponent, feks. JTable. Så læs APIen og the Java Tutorial: http://java.sun.com/docs/books/tutorial/uiswing/TOC.html
og gør så hvad de gør. Kom i gang med at lave egne modeller til Swing komponenter, forstå at specialisere Swing komponenter.. osv.

Jeg synes afgjort Swing er noget af det sværeste i Java. Det kræver meget øvelse at blive god til det, men når man så gør er det det bedste programmeringssprog til at designe brugergrænseflader i, synes jeg :)
Avatar billede r9 Nybegynder
19. marts 2003 - 20:06 #8
jeg er helt enig med dig i at GUI er en af de sværeste ting i Java.

Jeg har kodet noget GUI, men synes specielt at de forskellige layoutManagers er den sværeste del at finde rundt i.

Kan du give nogle tip på det område?
Avatar billede viht Nybegynder
19. marts 2003 - 20:13 #9
Det kan være tricky at bruge Layoutmanagers, men sørg for IKKE at følge denne cyklus:
- Lær kun de mest simple layout-managere at kende
- Bliv irriteret over hvor "dumme" de er
- Slå alle layout-managere fra
- Placer alt manuelt med pixels nøjagtighed (null layout!¤%&¤")
- Bliv træt af den tid det tager (det tager en evighed at justere)
- Brug en GUI-Builder (ALDRIG I LIVET!!)
- Bliv frustreret over ikke at kunne få det til at fungere sammen med sit program
- Begynde at programmere Visual Basic
- Lide hjernedøden :-)

Et par hints til layoutmanagers kan være:
- Dit hoved JFrame skal altid have BorderLayout. Enhver applikation du kigger på i Windows og andre operativsystemer indeholder komponeneter i den layout form, hvis du lægger mærke til det. (panel på venstre side. Stort panel midt på, og små paneler øvers(JMenu osv). Tænk bla. på Outlook: Et træ til venstre( BorderLayout.WEST), et stort panel i midten( BorderLayout.CENTER) - som består af 2 mindre paneler, hvor det ene indeholder en tabel og det andet et tekstfelt.

- Brug den simplest mulige LayoutManager du kan slippe afsted med og lær at se hvornår det måske er bedre at flytte det ud på to paneler i stedet. Du kan komme meget langt med paneler med BoxLayout og FlowLayout. Lær som en af de sidste LayoutManagers, GridBagLayout, som er rimelig kompleks.

- Brug www.docjava.dk til at lære om layouts, under sektionen Grafiske Brugergrænseflader.

- Lær at tegne brugergrænsefladen på et stykke papir og forestil dig hvordan du kan gøre det i Java.

- Øv dig, og hver gang du får en ide til noget du gerne vil lave, så sæt dig ned og lav det. Det bliver sjovere og sjovere jo bedre du bliver til det. Brugergrænsefladen er jo fra brugerens synspunkt vigtigste i et program, da det er det eneste han/hun ser. Vedkommende ser jo ikke om du har brugt 20 GoF mønstre i dit persistenslag, vel?
Avatar billede viht Nybegynder
19. marts 2003 - 20:14 #10
Og brug ALDRIG, ALDRIG null layout. Slå jer selv hver gang i får tanken :o))
Avatar billede viht Nybegynder
19. marts 2003 - 20:16 #11
Cyklusen er:

Lav noget simpelt --> få succesoplevelse --> lav noget lidt mere avanceret --> få succesoplevelse osv.. men spring ikke for langt frem ad gange, så bliver det uoverskueligt.
Avatar billede r9 Nybegynder
19. marts 2003 - 20:16 #12
god forklaring :-)
Avatar billede r9 Nybegynder
19. marts 2003 - 20:21 #13
Har du iøvrigt en forklaring på hvorfor Java's GUI er så relativ langsom?
Det er vist ikke helt forkelt, hvis man siger at det er den langsommeste GUI i alle sprog jeg kender.

Er det fordi at det skal kunne køre på alle platforme?

Eller har designerne bare ikke tænkt sig ordenlig om!
(Det er jo ingen hemmeligehed at de ikke var for heldige med AWT)
Avatar billede viht Nybegynder
19. marts 2003 - 20:24 #14
Well.. jeg vil ikke sige Swing er _langsomt_... jeg har set GUIer i C# der kører ringere. Du skal huske på at al Swing afvikles og emuleres i JVM, der er næsten ingen native afvikling af grafik og derved sænkes hastigheden.
Hvis Java kun skulle køre på Windows feks., så var det ikke noget problem bare at hooke ned i ren Windows grafik, men grafikken skal jo se ens ud i Linux, Unix og Windows.

JVM udfører når den tegner et JFrame ca. følgende:
1. Hvilken form skal jeg tegne?
2. Hvilket operativsystem er jeg på?
3. Tegn det jeg kan i native
4. emuler det jeg ikke kan tegne
Avatar billede arne_v Ekspert
19. marts 2003 - 20:30 #15
Nu er jeg mere teoretiker and praktiker m.h.t. Java GUI.

* Fordi Java skal køre på utallige platforme, så er der visse
  restriktioner på designet, hvilket formentligt giver lidt
  overhead.

* Fordi Java GUI skal gennem mange lag inden den når helt ud til
  hardware så er der formentligt lidt ekstra overhead.

* Swing er et rimeligt kraftfuldt GUI API, men det kræver også
  en del memory - mange langsomme Java GUI'er skyldes for lidt
  memory.

men langt den mest afgørende faktor er programmøren !

Der er rigtigt mange utroligt langsomem Java GUI'er.

Men der er også enkelte hurtige. Jeg er f.eks. meget
imporneret af JEdit.

Eclipse er dog også meget imponerende, så måske var SWT
værd at kigge på, hvis man ikke betragter det som blasfemisk.

:-)
Avatar billede r9 Nybegynder
19. marts 2003 - 20:32 #16
Kan SWT køre på andet end Windows?
Avatar billede arne_v Ekspert
19. marts 2003 - 20:36 #17
Ja da.

Windows, Linux, Solaris, AIX, HPUX.

Og jeg mener Mac er i beta.
Avatar billede viht Nybegynder
19. marts 2003 - 20:39 #18
Kender du nogle gode first time introduktioner til SWT arne?
Avatar billede arne_v Ekspert
19. marts 2003 - 20:50 #19
Avatar billede viht Nybegynder
19. marts 2003 - 20:53 #20
Tak for det.
Avatar billede arne_v Ekspert
19. marts 2003 - 20:55 #21
web_the_world>

Undskyld for at v lige har lånt dit spørgsmål til lidt Swing snak.

Du bruger bare vihts kommentarer og ignorerer de mere principielle
diskussioner om GUI i Java.
Avatar billede web_the_world Nybegynder
19. marts 2003 - 21:49 #22
arne v, viht

Det er helt ok - meget spændende læsning - specielt når det er de kloge der taler - og så lærer man jo en masse...Så det er skam helt ok...

og nok engang tak
Avatar billede arne_v Ekspert
26. marts 2003 - 22:13 #23
viht>

Jeg tro der ligger 30 nemme point for dig på http://www.eksperten.dk/spm/333629 !

(der skal laves et par combo boxe og laves en SQL sætning udfra
det valgte)
Avatar billede viht Nybegynder
27. marts 2003 - 00:57 #24
Det er jo appletter, det gider jeg ikke bøvle med :) Jeg afskyr apletter og arbejder hellere med Web Start/Swing.

Ellers tak for tippet :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester