Ausschluss bei Klick auf GUI Element

Schniegelmann

Neues Mitglied
Hallo zusammen,

ich bin neu hier und habe zur folgenden Frage leider noch nichts im Forum gesehen, daher einfach mal meine Frage:
Ich habe folgende Main-Klasse
Java:
public class Testframe extends JComponent implements Observer{

    private JFrame f;
    Element element1;
    Element element2;
    Element element3;
    GUICanvas canvas;
    ASTEvent event1;
    ASTEvent event2;
    ASTEvent event3;
    JButton send;
    Viewer viewer;
    
      public Testframe(){
        f = new JFrame("GUI");
        event1 = new ASTEvent("EventNAME1", "EventDATA1");
        event2 = new ASTEvent("EventNAME2", "EventDATA2");
        event3 = new ASTEvent("EventNAME3", "EventDATA3");
        element1 = new Element(event1);
        element2 = new Element(event2);
        element3 = new Element(event3);
        viewer = new Viewer();
        f.setSize(800,200);

        canvas = new GUICanvas();
        canvas.append(element1);
        canvas.append(element2);
        canvas.append(element3);
        
        Container content = f.getContentPane();
        content.setBackground(Color.gray);
        content.setLayout(new BorderLayout());
        content.add(viewer,BorderLayout.LINE_START);
        content.add(canvas,BorderLayout.CENTER);

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

      public static void main(String[] args){
          Testframe tf = new Testframe();
      }
}

Darin wird eine GUI aufgebaut, die die Elemente(ASTEvent) enthält. Ein Element wird gezeichnet mit der Funktion:
Java:
 @Override
    protected void paintComponent(Graphics graphics) {
        Graphics2D graphics2D = (Graphics2D) graphics;
        graphics2D.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        //
        Border border = null;

        Color color = null;
        if (mFocused) {
            color = mColor.brighter();
            //
        } else {
            color = mColor;
        }
        // Draw a gradient color
        GradientPaint paint = new GradientPaint(0, 0, color.darker(), 0, getHeight() / 2, color.brighter(), true);
        graphics2D.setPaint(paint);
        graphics2D.fillRect(0, 0, getWidth(), getHeight());

        graphics2D.setColor(Color.WHITE);
        graphics2D.setFont(new Font(Font.MONOSPACED, Font.ITALIC, 11));
        graphics2D.drawString(mASTEvent.getName(),
                getWidth() / 2 - getFontMetrics(new Font(Font.MONOSPACED, Font.ITALIC, 11)).stringWidth(mASTEvent.getName()) / 2,
                getHeight() / 2 + getFontMetrics(new Font(Font.MONOSPACED, Font.ITALIC, 11)).getHeight() / 1);
       
        graphics2D.drawString(mASTEvent.getData(),
                getWidth() / 2 - getFontMetrics(new Font(Font.MONOSPACED, Font.ITALIC, 11)).stringWidth(mASTEvent.getData()) / 2,
                getHeight() / 2 + getFontMetrics(new Font(Font.MONOSPACED, Font.ITALIC, 11)).getHeight() / 60);

        super.paintComponent(graphics);
    }

Auf diese Elemente kann nun geklicket werden per:
Java:
  @Override
    public void mouseClicked(MouseEvent event) {
        if (event.getButton() == MouseEvent.BUTTON1
                && event.getClickCount() == 1) {
            mSelected = !mSelected;
            if(mSelected){
                 setBorder(BorderFactory.createLineBorder(Color.RED));
                 revalidate();
                 repaint();
            }
            else {
                setBorder(BorderFactory.createLineBorder(new Color(0,0,100)));
                revalidate();
                repaint();
            }
        } else if(event.getButton() == MouseEvent.BUTTON3
                && event.getClickCount() == 1) {
            mContextMenu.show(this, event.getX(), event.getY());
        }
        revalidate();
        repaint();
    }
Hierbei ist mSelected ein bool Wert der zurückgibt, ob das Element ausgewählt ist. Das ausgewählte Element wurd nun rot umrandet. Allderdings ist nun das Problem, dass alle Elemente in der GUI an und abgewählt werden können (sie werden alle einzeln rot, wenn ich sie anklick). Ich möchte allerdings, dass wenn ein Element ausgewählt ist und dann ein anderes angeklickt wird, das alte abgewählt und das neu geklickte angewählt wird. (gekennzeichnet eben durch den roten Rahmen)

Ich versteh leider nicht, wie ich diesen Ausschluss bei der mouseClicked-Funktion erstellen kann.

Ich hoffe, ich konnte mein Problem klar darstellen. Wenn noch Fragen zum Verständnis sind, bitte posten.

Danke schonmal für Feedback
Schniegelmann
 
Naja im Prinzip willst Du ja die Radiobutton-Funktionalität nachbauen. Hab aber keine Lust mir all Deinen Code anzugucken 😉. Alle Elemente müssen Teil einer (nachgebauten) RadioButtonGroup sein und wenn ein Button geklickt wird, sagt er seiner Group "ich wurde geklickt", die den Zustand aller anderen Elemente auf ungeklickt/nichtRotUmrandet zurücksetzt. Und dann den ganzen Kram neu zeichnen.
 
Hi JanHH,

erstmal danke für deine Antwort.
ja genau diese Funktionalität, die du beschreibst, möcht ich umsetzen. Hättest du (oder auch jemand anderes🙂) einen Vorschlag, evtl auch CodeSnippets, wie ich das machen kann.

Kann ich die Funktionalität einer ButtonGroup (ähnlich Mutex) hierauf übertragen ?

Oder brauch ich da einen WorkAround, wenn ja, was gäbs da für Möglichkeiten ?
 
Hm das solltest Du doch auch alleine hinkriegen. Was ist denn dabei das Problem? Du brauchst eine Klasse für die Gruppe und jedes Element muss die Gruppe benachrichtigen, wenn es angeklkickt wurde. Die Gruppe kümmert sich dann darum, alle Element ausser dem angeklickten wieder auf den Normalzustand zurückzusetzen.
 
Mal eine andere Überlegung - ich hoffe ich verstehe das alles richtig - aber wäre es nicht möglich direkt JRadioButtons (mit ButtonGroup) zu nehmen und "einfach" deren paintComponent() auf deine Art zu überschreiben?
 
Naja glaube ich würde mir ne Klasse schreiben die von RadioButton abgeleitet ist, PaintComponent überschreiben, die kannst du dann zu einer ButtonGroup hinzufügen. Dann sollte es eigentlich klappen.

[Edit]
Ein kleines Beispiel, nix dolles sollte aber die vielleicht klar machen wie ich es meine:
Java:
public class Radio extends JRadioButton {
    private boolean mFocused;
    
    public Radio() {
        this.setBounds(0, 0, 20, 20);
        this.setSize(100, 100);
    }
    
    
    @Override
    protected void paintComponent(Graphics graphics) {
        Graphics2D graphics2D = (Graphics2D) graphics;
        graphics2D.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        //
        Border border = null;
 
        Color color = null;
        // Draw a gradient color
        GradientPaint paint = new GradientPaint(0, 0, color.black, 0, getHeight() / 2, color.red, true);
        graphics2D.setPaint(paint);
        graphics2D.fillRect(0, 0, getWidth(), getHeight());
 
        graphics2D.setColor(Color.BLACK);
        graphics2D.setFont(new Font(Font.MONOSPACED, Font.ITALIC, 11));
        super.paintComponent(graphics);
    }
}

Die kannst du dann so zu einer Group hinzufügen, die für dich dann regelt das nur einer angeklickt werden kann:
Java:
        ButtonGroup gruppe = new ButtonGroup();
        gruppe.add(radio1);
        gruppe.add(radio3);
 
Zuletzt bearbeitet:
Lege dir doch einfach eine Variable an, die bei den mouseClicked-Events über
Java:
event.getSource()
mit dem Objekt des auslösenden Buttons belegt wird und versetze dann einfach über dieses Objekt den auslösenden Button wieder in den nicht-ausgewählten Modus. Das geht aber nur, wenn du den MouseListener nicht in der Klasse des Buttons definierst, sondern in deiner GUI-Klasse beim Hinzufügen der Komponenten "anhängst". Sonst wird der Zugriff auf die Variable (die ja in der GUI-Klasse liegen muss, damit sie global verwendet werden kann) schwierig.
 

Zurück
Oben