zmiana wyglądu komponentu Swing

Odpowiedz Nowy wątek
2011-09-12 09:51
0

Witam,

Chciałbym zmienić wygląd komponentu, żeby działałał jak JCheckBox, ale wygladał inaczej. Przesłaniam, więc metodę paintComponet(Graphics g), żeby rysowała krzyżyk i wszystko dzaiła, jeśli w środku mam instrukcję "super.paintComponent(g);", ale wtedy rysuje się też ten standardowy komponent, a tego nie chcę.
Jak wywalę tę instrukję, to nie działa jak należy, bo po odchaczeniu krzyżyk nie znika (znika dopiero przy zmianie wielkości okna), a nie chcę wstawiać instrukcji wymazania, żeby nie zamazywało mi tła.

Jak to poprawić?

Wrzucam caly kod, ale chodzi oczywiście o poprawkę w ostatniej klasie Krzyzyk


import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;

public class test{
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable(){
            public void run(){
                JFrame ramka=new Ramka();
                ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                ramka.setVisible(true);
            }
        });
    }
}
class Ramka extends JFrame{
    public Ramka(){
       setSize(300,300);
       setLayout(new FlowLayout());

       add(new Krzyzyk());
       add(new JButton("przycisk"));
       add(new Krzyzyk());
       add(new Krzyzyk());
    }
}
class Krzyzyk extends JCheckBox{
    public void paintComponent(Graphics g){
       //super.paintComponent(g);
        g.drawRect(0, 0, getHeight(), getWidth());

        if(this.isSelected()){
            g.drawLine(0, 0, getHeight(), getWidth());
            g.drawLine(getHeight(), 0, 0, getWidth());
        }
    }
}
edytowany 1x, ostatnio: Tompey, 2011-09-12 09:51
Zawsze mi się wydawało, że we wszelkich funkcjach draw najpierw podaje się współrzędną poziomą lub szerokość, a potem pionową lub wysokość. - Olamagato 2011-09-12 15:22

Pozostało 580 znaków

2011-09-12 13:05
0

Nie czyścisz miejsca gdzie to ma być rysowane. Metoda clearRect. Zamień te drawRect na clearRect, a jak chcesz tą ramkę, to skopiuj to i odejmij 1 od wysokości i szerokości.

       g.clearRect(0, 0, getHeight(), getWidth());
       g.drawRect(0, 0, getHeight()-1, getWidth()-1);

Pozostało 580 znaków

2011-09-12 13:44
0
Razi91 napisał(a)

Nie czyścisz miejsca gdzie to ma być rysowane.

zgadza się nie czyszczę, bo te elementy mają być na tle obrazka, którego nie chcę zamalowywać w całym miejscu, gdzie jest komponent. Chcę postawić tylko krzyżyk czy "ptaszek", ale żeby tło zostało, a nie taki pusty kwadrat.

edytowany 5x, ostatnio: Tompey, 2011-09-12 14:09

Pozostało 580 znaków

2011-09-12 14:15
0

No to musisz to tło narysować w tym miejscu gdzie był krzyżyk. Innego wyjścia nie ma.


Pozostało 580 znaków

2011-09-12 14:24
0
byku_guzio napisał(a)

No to musisz to tło narysować w tym miejscu gdzie był krzyżyk. Innego wyjścia nie ma.

czyli jak mam tło z pliku jpg to muszę pisać kod, który jeszcze raz odrysowuje ten fragment obrazka???
Nie da się jakoś łatwiej? Wszystko wygląda prawidłowo po zmianie wielkości okna myszką? Najeżdzam na kwadrat, klikam i pojawia się krzyżyk, znów klikam i nic się nie dzieje, ale po zmianie wielkości okna krzyżyk znika.

edytowany 1x, ostatnio: Tompey, 2011-09-12 15:01

Pozostało 580 znaków

2011-09-12 15:36
0

Jeżeli nie użyje się clearRect, to podczas kasowania krzyżyka nie będzie on w żaden sposób zmazany z tła. Trzeba by użyć tryb XOR i jeszcze liczyć rysowania w tym trybie.

class Krzyzyk extends JCheckBox
{
    public Krzyzyk()
    {
        setPreferredSize(new Dimension (100, 20));
    }

    @Override public void paintComponent(Graphics g)
    {
        final int w = getWidth() - 1, h = getHeight() - 1;
        g.clearRect(0, 0, w, h);
        g.drawRect(0, 0, w, h);
        if(this.isSelected())
        {
            g.drawLine(0, 0, w, h);
            g.drawLine(w, 0, 0, h);
        }
    }
}

Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 2x, ostatnio: Olamagato, 2011-09-12 15:59

Pozostało 580 znaków

2011-09-13 09:19
0

Dziękuję za dotychczasowe odpowiedzi

można też przerobić trochę ramkę i umieścić Krzyzyk jako klasę wewnętrzną z actionListener

class Ramka extends JFrame{
    public Ramka(){
       setSize(300,300);
       setLayout(new FlowLayout());
       getContentPane().setBackground(Color.YELLOW);

       add(new Krzyzyk());
       add(new JButton("przycisk"));
       add(new Krzyzyk());
       add(new Krzyzyk());
       ramka=this;
    }

    Ramka ramka;

    class Krzyzyk extends JCheckBox{
        public Krzyzyk(){
            super();
            this.addActionListener(new ActionListener(){
               public void actionPerformed(ActionEvent event){
               ramka.repaint();
            }
            });
        }
        public void paintComponent(Graphics g){
            g.drawRect(0, 0, getHeight()-1, getWidth()-1);

            if(this.isSelected()){    
                g.drawLine(0, 0, getHeight(), getWidth());
                g.drawLine(getHeight(), 0, 0, getWidth());
            }
        }
    }
}
}

działa, choć nie chciałem robić z Krzyzyka klasy wewnętrznej

edytowany 2x, ostatnio: Tompey, 2011-09-13 10:28

Pozostało 580 znaków

2011-09-13 11:56

Być może wystarczyło by przerysować rodzica (getParent()), o ile to rodzic ma te tło.

Możesz też przekazać referencje do ramki w konstruktorze.

To mogłoby działać w połączeniu z setXORmode(). - Olamagato 2011-09-13 12:44

Pozostało 580 znaków

2011-09-13 12:46
0
Razi91 napisał(a)

Być może wystarczyło by przerysować rodzica (getParent()), o ile to rodzic ma te tło..

O to chodziło, w actionListener komenda

getParent().repaint();

załatwia sprawę i klasa nie musi być wewnętrzna :)

Dziękuję:)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0