JButtons haben nicht immer lust zu erscheinen

Status
Nicht offen für weitere Antworten.
Hallo,
ich schreibe grade mein erstes programm mit swing und awt und habe ein problem mit JButtons.
Da ich keine Ahnung habe an welcher Stelle das Problem liegt, hoffe ich dass es ok ist wenn ich einfach mal den ganzen code poste:


Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class DrawPanel extends JPanel{

        private JButton book;
        private JButton stats;
        protected JButton admin;



@Override
public void paintComponent(Graphics g){


    super.paintComponent(g);


    int width = getWidth();
    int height = getHeight();

    g.setColor(Color.BLACK);
    g.fillRect(0, 36, width, 3);

    book = new JButton ("Booking");
    book.setVisible(true);
    add (book);
    stats = new JButton("Statistics");
    stats.setVisible(true);
    add(stats);
    admin = new JButton("Admin");
    admin.setVisible(true);
    add(admin);


    setVisible(true);

}
}


das ganze rufe ich dann von der main-klasse aus so auf:


Code:
DrawPanel x = new DrawPanel();

JFrame application = new JFrame("Flight Reservation System");

application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(x);
application.setSize(650,500);
application.setVisible(true);


so weit so gut, ab und zu funktioniert das ganze auch. allerdings nicht immer. die JButtons tauchen komischerweise nur bei ungefähr jedem zweiten aufruf des programms auf. Ich arbeite mit Netbeans und nach dem drücken des "Run Main Project"-Knopfes ist es reine glücksache, ob die buttons erscheinen oder nicht. Und das obwohl ich am code nichts ändere. Wenn die buttons nicht erschienen sind und ich die größe des Applet-Fensters ändere tauchen sie auf (allerdings gleich in mehrfacher ausführung).

Kann mir irgendjemand erklären woran das liegt und wie ich das beheben kann?

vielen dank schonmal!


Hier noch Systeminfos:
Product Version: NetBeans IDE 6.5 (Build 200811100001)
Java: 1.6.0_07; Java HotSpot(TM) Client VM 10.0-b23
System: Windows Vista version 6.0 running on x86; Cp1252; de_DE (nb)
 
nicht setVisible(true) pro JButton aufrufen, der eine Aufruf an application am Ende reicht

edit:
in paintComponent() haben derartige add()-Aufrufe noch weniger zu suchen,
das gehört in den Konstruktor von DrawPanel!

individuelles Zeichnen zusammen mit enthaltenen Standardkomponenten kann zu Problemen führen,
wenn du schon irgendwo malst, dann in einem exklusiven Bereich für ein paint-JPanel ohne Buttons usw.
 
Zuletzt bearbeitet von einem Moderator:
ja genau, in den paint-methoden sollten wirklich nur paint-sachen drin sein. diese methode wird eben immer aufgerufen, wenn neu gezeichnet werden muss. das kann unter umständen mehrere 100 mal pro sekunde sein.
d.h. du würdest den button auch jedes man neu definieren und auf die komponente adden.

ich weiß ja nicht genau, was dein zweck ist, aber am besten wäre es sicherlich, das draw-panel nur mit dem drawRect() zu gestalten und in dem main-programm die button auf das draw panel adden.

also z.b. so

[HIGHLIGHT="Java"]
application.add(x);
book = new JButton ("Booking");
x.add (book);
[/HIGHLIGHT]

ein book.setVisible(true) braucht man nicht. das geschieht automatisch
 
ok danke euch beiden, jetz klappts =)

noch ne andere frage (sorry schon wieder ne blöde frage, aber ich bin echt anfänger auf dem gebiet):

also diese 3 buttons sollen als menü fungieren und je nachdem welcher button angeklickt wurde soll was anderes von der paint methode gezeichnet werden. könntet ihr mir so grob erklären nach welchem prinzip ich das machen könnte?
meine eine erste idee wäre gewesen, dass beim buttonklick einfach eine variable geändert wird und ich in der paintComponent Methode nach if-abfrage dieser variable jeweils andere sachen zeichnen lasse. dann müsste ich aber in der main-methode ne endlosschleife mit "repaint()" machen und dass is ein bisschen zu unperformant ^^
 
da es dein ersten programm ist gebe ich dir gleich mal nen tipp, wie du bestimmen kannst, was passieren soll, wenn du auf einen button klickst.

[HIGHLIGHT="Java"]
book.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
// hier die akion reinschreiben
}
});
[/HIGHLIGHT]

sieht für für anfänger sicher kryptisch aus. was dort passier ist folgendes:
man führt dem button einen Listener hinzu. Dieser "lauscht" so zu sagen auf bestimmte Aktionen. Beim Button ist das eben z.b. ein mausklick. wenn geklickt wurde wird ein ActionEvent geworfen und kommt in der methode actionPerformed an. diese methode wird also aufgerufen wenn geklickt wurde. alles was du da reinschreibst wird dann ausgeführt.

hoffe, ich hab dir was neues erzählt 🙂
 
Hier hab ich mal was für dich.
Spiel ein bischen damit rum wenn was unklar ist dann frag nach...
In deer FAQ gibts es auch ein gutes Tutorial wie man am besten zeichnet

[HIGHLIGHT="Java"]

public class MainDrawPanel extends JPanel{

DrawPanel drawPanel;
MenuePanel menuePanel;

public MainDrawPanel()
{
super(new BorderLayout());
drawPanel = new DrawPanel();
drawPanel.setBorder(BorderFactory.createTitledBorder("Draw"));
menuePanel = new MenuePanel();

add(drawPanel, BorderLayout.CENTER);
add(menuePanel, BorderLayout.NORTH);

}

class DrawPanel extends JPanel
{
Shape shape;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if(shape != null)g2.draw(shape);
}

public void drawOperation(Shape shape)
{
this.shape = shape;
repaint();
}
}



class MenuePanel extends JPanel
{
public MenuePanel()
{
JButton linie = new JButton("Linie");
linie.addActionListener(new ActionListener()
{

public void actionPerformed(ActionEvent e) {
drawPanel.drawOperation(new Line2D.Double(10.0,10.0,100.0,30.3));

}

});
JButton kreis = new JButton("Kreis");
kreis.addActionListener(new ActionListener()
{

public void actionPerformed(ActionEvent e) {
drawPanel.drawOperation(new Ellipse2D.Double(10,10,50,50));

}

});
JButton rechteck = new JButton("Rechteck");
rechteck.addActionListener(new ActionListener()
{

public void actionPerformed(ActionEvent e) {
drawPanel.drawOperation(new Rectangle(100,10,40,50));

}

});
add(linie);
add(kreis);
add(rechteck);
}
}

public static void main(String[] args) {
JFrame frame = new JFrame("Draw");
frame.add(new MainDrawPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}


[/HIGHLIGHT]
 
Zuletzt bearbeitet von einem Moderator:
oh, da war ja schon jemand schneller als ich.
ich hab dir auch mal was geschrieben.

DrawPanel ist hier eine innere klasse. die kannst du auch einfach als eigene klasse schreiben, denn muss man sie nicht so komisch deklarieren.

wie du siehst, habe ich einige variablen als static final... usw mit passenden namen definiert. das ist ein guter stil um von außen die variable festzulegen, die bestimmt was gezeichnet werden soll.


[HIGHLIGHT="Java"]
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MenuButton extends JFrame{

public MenuButton(String title){
super(title);
setSize(350, 150);
// EDIT
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args) {
MenuButton mb = new MenuButton("Test");

JPanel panel = new JPanel();
final DrawPanel drawPanel = mb.new DrawPanel(350,100);
JButton dr = new JButton("Draw Rect");
JButton fr = new JButton("Fill Rect");
JButton dc = new JButton("Draw Circle");

mb.add(panel);
panel.add(dr);
panel.add(fr);
panel.add(dc);
panel.add(drawPanel);

dr.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
drawPanel.setDrawItem(DrawPanel.DRAW_RECT);
drawPanel.repaint();
}
});

fr.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
drawPanel.setDrawItem(DrawPanel.FILL_RECT);
drawPanel.repaint();
}
});

dc.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
drawPanel.setDrawItem(DrawPanel.DRAW_CIRCLE);
drawPanel.repaint();
}
});


mb.setVisible(true);
}


class DrawPanel extends JPanel{

public DrawPanel(int width, int height){
super();
setSize(width, height);
setPreferredSize(new Dimension(width,height));
setOpaque(false); // das braucht man hier, damit die grafik wieder ganz neu gezeichnet wird
}

public final static int DRAW_RECT = 0;
public final static int FILL_RECT = 1;
public final static int DRAW_CIRCLE = 2;
private int drawItem;

public void setDrawItem(int item){
drawItem = item;
}

public void paintComponent(Graphics g){
switch (drawItem) {
case DRAW_RECT:
g.drawRect(0, 0, 60, 60);
break;
case FILL_RECT:
g.fillRect(0, 0, 60, 60);
break;
case DRAW_CIRCLE:
g.drawOval(0, 0, 60, 60);
break;
}
}
}
}[/HIGHLIGHT]
 
Zuletzt bearbeitet:
Du musst bedenken wenn du dein altes schon mal gezeichnetes beibehalten willst... Musst du es "speichern" z.B. in einer ArrayList ...

@divd85
Naja mit deinen ganzen finals wird es schnell unübersichtlich wenn du jetzt viele Shapes hast...
und der switch/if ist ja nicht notwendig...

EDIT: ich weiß nicht was du vorhast und wieviel shapes du anbieten willst aber ich würde anstatt ein panel wo die buttons drin sind... eventuell eine toolbar oder sowas dafür machen...
 
Zuletzt bearbeitet von einem Moderator:
Status
Nicht offen für weitere Antworten.

Zurück
Oben