Suwak przewijania

1

Witam.
Mam problem z suwakiem przewijania :/ Nie mogę zrobić, aby w końcu on sie pojawił w okienku...
Mam główne okno dziedziczące po JFrame. W nim są dwa JPanele. Chcę dodać suwak do drugiego JPanelu.
Próbowałem JScrollPane i JScrollBar, wstawiałem je raz do JFrame'a, raz do JPanela. Nawet jak mi się program kompilował, to suwak mi sie nie pojawiał :/

Drugie pytanie.
Te JPanele robię bez Layoutów. Żeby mi się wyświetlały oba w jednym oknie uzyłem metody setBounds.
Co zrobić żeby ten drugi JPanel zawsze dopasowywał się do wielkości JFrame?

0

JPanel ma być dzieckiem JScrollPane.

EDIT:
Ok, źle. Nie dzieckiem, a widokiem viewportu.

0

A dokładniej?
Jak dodałem JPanel extends JScrollPane to dalej nie działa.

W tym oknie głównym JFRame, dodałem taki kawałek kodu:

suwak = new JScrollPane(d);
    	add(suwak); 

gdzie d to ten JPanel dziedziczący po JScrollPane.

A może w innym miejscu mam to napisać?

0

Spróbowałem troszkę inaczej:

 DrawPane d = new DrawPane();
    	
    	suwak = new JScrollPane(d, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
    	suwak.setBounds(200, 0, (int)dim.getWidth()-200,(int)dim.getHeight());

I dalej nie działa...

0

Zauważyłem, że wyżej nie napisałem wszystkiego.
Tu pełny kod okienka JFrame:

public Window(Dimension dim) {   	
    	setLayout(null);
    	Container contents = getContentPane();
    	DrawPane d = new DrawPane();
    	
    	suwak = new JScrollPane(d, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
    	suwak.setBounds(200, 0, (int)dim.getWidth()-200,(int)dim.getHeight());
    	Menu m = new Menu (d);
    	m.setBounds(0,0,200,(int)dim.getHeight());
    	contents.add(m);
    	contents.add(suwak);
    } 
0

Mi działają suwaki, zrobiłem to tak:

class MyFrame extends JFrame{
	public MyFrame(){
		setSize(400,300);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		JPanel panelA = new JPanel();
		panelA.add(new JLabel("Panel A"));
		JPanel panelB = new JPanel();
		panelB.add(new JLabel("Panel B"));
		JScrollPane scroll = new JScrollPane(panelB,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		add(panelA,BorderLayout.SOUTH);
		add(scroll,BorderLayout.CENTER);
	}
}

0

Ok, dzieki ;D Suwaki sie pojawiły.
A teraz - jak zrobić, by te suwaki zaczęły działać?
Tzn. ten JPane z suwakiem ma podany rozmiar w setBounds. Jak zrobić by on się powiekszał i pozwalał działać suwakowi, jeśli obrazek jest wiekszy od okna? Próbowałem z setPreferredSize(), ale nie działa...

0

Jeżeli na panelu dodanym do panelu scorll znajdzie się coś co będzie miało większego od rozmiarów panelu, automatycznie suwki zostaną odblokowane i będą działać np:

JPanel panelB = new JPanel();
		panelB.add(new JLabel("Panel B"));
		String[] a = {"ppp","ppp"};
		JList lista = new JList(a);
		lista.setFixedCellHeight(500);
		panelB.add(lista);
		JScrollPane scroll = new JScrollPane(panelB,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		add(scroll,BorderLayout.CENTER);
0

Poszukiwacz chyba chce coś na tym panelu rysować, w takim razie nic nie sprawdza, czy obszar rysowania nie wyjeżdża za obszar Viewportu.
JPanel.setPreferredSize() (dla JPanela, nie JScrollPane'a) powinno zadziałać, jeśli Layout JScrollPane'a nie jest nullem.

0

Z layoutami działa, ale...
Jak zrobić, by móc guziki w menu, czyli lewym JPanelu samemu poustawiać? GridLayout mi zupełnie nie pasuje.

I drugie ale - gdy okienko nie jest na full screen, to suwaki są, ale nieaktywne...

0

Scrolle działają, ale nie do końca prawidłowo.
Jak wczytam obrazek lub go przetransformuję, to suwaki sie nie pojawiają. Pojawiają się dopiero jak zmienię rozmiar okna (tzn. gdy dam na fullscreen, albo go rozciągnę). O co chodzi?

0

Szkoda, że goście nie mają edycji postów :P

Żeby była jasnośc jaki mam teraz problem.
Mam JFrame'a, w nim dwa JPanele. Drugi JPanel jest JScrollPanem i jednocześnie obszarem do rysowania. Gdy wczytuję do tego drugiego JScrollPane'a jakiś obrazek, to daję tam setPreferredSize() żeby było ok dla danego obrazka. Jednak scrolle uaktywniają się dopiero, gdy zmienię rozmiar JFrame'a. Dodanie repaint() po setPreferredSize() nic nie zmienia.
Co zrobić, aby po wczytaniu dużego obrazka, JFrame/JScrollPane od razu się uaktualnił i pojawiły się suwaki?

0

validate() może

0

Zależy jeszcze, w którym miejscu powinien być?
Bo po metodzie setPreferredSize(), która jest po wczytaniu obrazka, nie działa :/
Poczytałem o tym validate() i wygladało na to, że juz bedzie ok...

Może chodzi o to, że trzeba wysłać informację do głównego JFrame'a, żeby się zaktualizował? Bo validate() był w JPanelu, który jest częścią JFrame'a. A może trzeba własnie wysłac informację wyżej? Tylko, że z poziomu JPanela nie mam dostępu do JFrame'a.
Sam nie wiem... Bo próbowałem naprawdę różnymi sposobami robić, by te suwaki działały od początku :P

0

Ok, to może rzucę trochę kodem :P

W mainie tworzę JFrame:

 public static void main(String[] args) {
		Toolkit scrinfo = Toolkit.getDefaultToolkit();
        Dimension dim = scrinfo.getScreenSize();
		Window wnd = new Window(dim);
        wnd.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        wnd.setVisible(true);
        wnd.setSize(900, 600);
        wnd.setTitle( "Przekształcenia afiniczne. Autor: Tadeusz Cekała" );
        wnd.setLocationRelativeTo(null);
	}

Ten JFrame wyglada tak:

 class Window extends JFrame  {	
	JScrollPane suwak;
	
	public Window(Dimension dim) {   	
    	setLayout(new BorderLayout());
    	Container contents = getContentPane();
    	DrawPane d = new DrawPane();
    	Menu m = new Menu (d);
    	JScrollPane scroll = new JScrollPane(d);
    	contents.add(m, BorderLayout.WEST);
    	contents.add(scroll,BorderLayout.CENTER);
    }
}

A DrawPane, który ma mieć suwaki, wyglada tak:

 class DrawPane extends JPanel {
	public BufferedImage img, img2;
public DrawPane() {
		super();
		setLayout(new GridLayout(1,1));
		setBackground( new Color(153, 204, 255) );
}
public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
                g2d.drawImage(img2,szerokosc/2,wysokosc/2, null);
	    	setPreferredSize(new Dimension(img2.getWidth()*2, img2.getHeight()*2));
	    	repaint();
}

I jak wczytam obrazek większy niż okno, to suwaki pojawiają się dopiero gdy zmienię rozmiar tego okna (tzn. pociągnę za róg tego okna).
Bardzo zalezy mi na rozwiązaniu problemu :(

0

Wtf?

public void paintComponent(Graphics g) {
                    ...
                    setPreferredSize(new Dimension(img2.getWidth()*2, img2.getHeight()*2));
                    repaint();
}

repaint() wywołane z metody paintComponent()? Coś w rodzaju nieskończonej pętli, jak skończysz malować, to zacznij malować na nowo.
repaint() (i setPreferredSize()) powinny być wykonane raz, zaraz po ustaleniu img2, tzn. po odczytaniu obrazka.

0

Brakuje Ci współpracy między oknami (klasami). Po pierwsze zamień, to

DrawPane d = new DrawPane(this);

na

    DrawPane d;  //deklaracja pola
    ...
    d = new DrawPane(this);

Będziesz miał zawsze dostępną w klasie referencję do okna DrawPane i będziesz mógł coś w tym oknie zmienić, np. po odczytaniu nowego obrazka.
Po drugie dodaj w klasie DrawPane pole będące referencją do okna Window.

 class DrawPane extends JPanel {
        public BufferedImage img, img2;
        private Window parent
public DrawPane(Window parent) {
                super();
                this.parent=parent;
                ....

Będziesz miał w oknie DrawPane referencję do okna Window.

0

Bardzo dziękuję za odpowiedź.

Jeśli chodzi o repaint(), to faktycznie - mój błąd :P
setPreferredSize() przeniosłem do czynności, które są wykonywane po nacisnięciu guzika. Gdy zostanie on naciśnięty zostają wykonane operacje:

 d.file=wybierzPlik();
				d.wczytaj();
				d.setPreferredSize(new Dimension(d.img2.getWidth()*2, d.img2.getHeight()*2));
				d.opcja=7;
				d.repaint();

Te instrukcje znajdują się w klasie Menu.
Niestety suwaki dalej pojawiają się dopiero po rozciągnięciu okienka.

Poprawiłem DrawPane'a, dodałem mu referencję do okna Window. Ale co dalej?
Probowałem dodać parent.validate() po zmianie rozmiaru okna, ale dalej nic...

Problem z suwakami dalej ejst. Pojawiają się dopiero po rozciągnięciu okna.

0

Trudno zgadywać co masz źle, pokaż kod.

0

W związku z tym, ze mój kod jest baardzo długi zamieszczam interesujące części ;P

 
public class Main {

	public static void main(String[] args) {
		Toolkit scrinfo = Toolkit.getDefaultToolkit();
        Dimension dim = scrinfo.getScreenSize();
		Window wnd = new Window(dim);
        wnd.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        wnd.setVisible(true);
        wnd.setSize(900, 600);
        wnd.setTitle( "Przekształcenia afiniczne. Autor: Jan Kowalski" );
        wnd.setLocationRelativeTo(null);
	}
}

class Menu extends JPanel implements ActionListener {
	public JButton b1, b2, b3, b4, b5, b6, b7, b8;
	public DrawPane d;
	
	public Menu(DrawPane d) {
		super();
		this.d = d;
    	
		setLayout(new GridLayout(8,1));
		
		b7 = new JButton("Wczytaj obraz rastrowy");
		b7.setVisible(true);
		add(b7);
		
		b5 = new JButton("Wczytaj macierz");
		b5.setVisible(true);
		add(b5);
	
		b5.addActionListener( this );
		b7.addActionListener( this );
		
		setVisible(true);
		d.opcja = 0;
	}
	
	public void actionPerformed(ActionEvent event)
	{
		Object source = event.getSource();
		if (source == b5) {
			try {
				d.file2=wybierzPlik(); //zwraca wybrany File
				wczytajMacierz();  //wczytuje macierz przeksztalcen pod pole d.macierz
				d.przeksztalcRastrowo(new Macierz());  //przeksztalca obraz podana macierzą
				d.opcja=8;
				d.repaint();
			} catch (Exception e) {}
		}
		else if (source == b7) {
			try {
				d.file=wybierzPlik();
				d.wczytaj(); //wczytuje obraz
				d.setPreferredSize(new Dimension(d.img2.getWidth()*2, d.img2.getHeight()*2));
				d.opcja=7;
				d.repaint();
			} catch (Exception e) {}
		}
	 }
}

class DrawPane extends JPanel {
	
	public int opcja;
	public Macierz macierz;
	public File file, file2;
	public BufferedImage img, img2;
	public int szerokosc, wysokosc, szerokosc2, wysokosc2, oX, oY;
	public Window parent;
	
	public DrawPane(Window parent) {
		super();
		setLayout(new GridLayout(1,1));
		setBackground( new Color(153, 204, 255) );
		opcja = 0;
		this.parent = parent;
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		
		szerokosc = getWidth();
		wysokosc = getHeight();
		
	    if(opcja==7 || opcja==8) {
	    	if(opcja==7) { //to jest wywoływane po wczytaniu obrazka, gdy pojawia się on po raz pierwszy na ekranie. Suwaki pojawiają się dopiero po rozciągnięciu
	    		g2d.drawImage(img2,szerokosc/2,wysokosc/2, null);
	    		oX = getWidth()/2;
	    		oY = getHeight()/2;
	    	}
	    	else if (opcja==8){
	    		if(oX==getWidth()/2 && oY==getHeight()/2) //przy rozciąganiu okienka, obrazek musi sie przenosić, dlatego ta część jest taka dziwna :P
	    			g2d.drawImage(img2,0,0, null);
	    		else {
	    			przeksztalcRastrowo(new Macierz());
		    		g2d.drawImage(img2,0,0, null);
		    		oX=getWidth()/2;
		    		oY=getHeight()/2;
	    			repaint(); //tu musi byc repaint, bo inaczej nie dziala dobrze :P
	    		}
	    	}
	    }
	}
	
	public void wczytaj() throws IOException {
		img = ImageIO.read(file);
		img2 = ImageIO.read(file);
		macierz = new Macierz();
	}
}

class Window extends JFrame  {	
	JScrollPane suwak;
	DrawPane d;
	
	public Window(Dimension dim) {   	
    	setLayout(new BorderLayout());
    	Container contents = getContentPane();
    	d = new DrawPane(this);
    	Menu m = new Menu (d);
    	JScrollPane scroll = new JScrollPane(d);
    	contents.add(m, BorderLayout.WEST);
    	contents.add(scroll,BorderLayout.CENTER);
    }
}

To są te rzeczy, które są powiazane z niepojawianiem sie suwaków. Pozostała część kodu to zupełnie niepowiązane metody :P

0

W starszej wersji miałeś

new JScrollPane(d, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

Co się stało z drugim i trzecim argumentem?
Dopóki masz repaint() wywołane z paintComponent(), to masz program zrypany.

0

Jeśli chodzi o repainty, to masz rację.
Miałem gdzie indziej błąd i w sumie z repaintem tez nie działało ;P Po prostu poprawiajac jedna rzecz potrafię zepsuc inną ;)

A te constanty zniknęły, bo widziałem w necie, że nie sa one wymagane.
Poza tym one nic nie zmieniaja. Jak wczytam za duzy obraz, to te suwaki są nieaktywne. Zaczynają działac dopiero po rozciągnięciu okna.

0

Trzeba JScrollPane poinformować o zmianie zawartości.

       d.opcja=7;
       d.parent.scroll.setViewportView(d);
       d.repaint();
0

Niestety.
Po dodaniu tej linijki suwaki dalej zaczynają działac dopiero po rozciągnięciu.
A dodatkowo wczytany obraz pojawia się dopiero po rozciągnięciu.
Więc jest jeszcze gorzej :(

0

U mnie działa, zapomniałem Ci napisać o jeszcze jednej zmianie, scroll jest polem klasy a nie zmienną lokalną.

class Window extends JFrame  {
        JScrollPane scroll;
        DrawPane d;

        public Window(Dimension dim) {
            setLayout(new BorderLayout());
            d = new DrawPane(this);
            Menu m = new Menu (d);
            scroll = new JScrollPane(d);
            add(m, BorderLayout.WEST);
            add(scroll,BorderLayout.CENTER);
    }
}
0

Jesteś wielki!
Wszystko działa :D
Bardzo dziękuję za pomoc, bo szczerze mówiac już nie miałem nadziei, że sobie z tym poradzę.

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