zmiana wyglądu komponentu Swing

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());
        }
    }
}
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);
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.

0

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

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.

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);
		}
	}
}

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

0

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.

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ę:)

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