Swing JScrollPane/Layoutmanger Problem bei dynamischer Größenänderung

guarditan

Mitglied
Hallo 🙂,

ich kämpfe in letzter Zeit mit einem Problem. Ich will nämlich mir ein Fenster erstellen, dass aus beliebig vielen Buttons besteht. Ich habe mir das momentan so gedacht, dass ich das Fenster mit nem GridBaglayout gestalte. In die erste Zeile kommen zwei Buttons und eine Combobox. In die zweite Zeile kommt das JScrollPane. Diesem wird ein JPanel übergeben, welches die ganzen Buttons verwalten soll. Das funktioniert alles soweit prima, solang die Buttons "ohne scrollen" darstellbar sind. Sobald es zu viele werden, bekomme ich keine gescheite Anzeige mehr hin. Ich fürchte irgendwie, dass der Layoutmanger dran Schuld sein könnte, bin mir aber nicht sicher. Habe da auch schon mehrere versucht von Grid, GridBag, Null, usw.

Habt ihr da ne Idee oder wie würdet ihr das am besten lösen ?

Problem ist ja ganz einfach. Ganz viele Buttons auf dem Fenster mit fester Größe. Zudem halt Scrollbalken damit auch alle Buttons erreichbar sind.
 
Ich habe mal versucht mein Beispiel möglichst klein zu halten. Aber so sollte es Problemlos compilieren. Die Variable count (zeile 99/100) zeigt die quadratische Anzahl an Buttons. Bei 12 funktioniert sie prima, bei 32 nicht mehr. Ich hoffe das hilft 🙂


Java:
import javax.swing.JFrame;
import java.awt.Adjustable;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.awt.Toolkit;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.tree.DefaultMutableTreeNode;


 
class test extends JFrame
{ 
	
	public static void main(String[] args){
		test t = new test();
		t.genWindowNewGrid();
		
	}
	
			
	public test(){
			
			this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
			this.setSize(Toolkit.getDefaultToolkit().getScreenSize());
		    this.setResizable(false);
		    this.setUndecorated(false);
		    
		}
		
		
		private GridBagConstraints setCons(int x, int y, int gx, int gy, double wx, double wy){
			GridBagConstraints gbc = new GridBagConstraints();
			gbc.gridx = x;
		    gbc.gridy = y;
		    gbc.gridwidth = gx;
		    gbc.gridheight = gy;
		    gbc.weightx = wx;
		    gbc.weighty = wy;
		    gbc.insets = new Insets(1,1,1,1);
		    //gbc.anchor = GridBagConstraints.CENTER;
		    return gbc;
		}
		
	private void genWindowNewGrid(){
		
		this.getContentPane().removeAll();
		
		GridBagLayout gbl = new GridBagLayout();
		this.setLayout(gbl);
		GridBagConstraints gbc = new GridBagConstraints();
		
		String[] jcomboContent = {"right","down","column","row"};
		JComboBox jcombo = new JComboBox(jcomboContent);
		gbc = setCons(0,0,1,1,0,0);
	    this.add(jcombo);
	    gbl.setConstraints(jcombo, gbc);
	    
	    JButton jBtnSave = new JButton("save");
	    gbc = setCons(1,0,1,1,0,0);
	    this.add(jBtnSave);
	    gbl.setConstraints(jBtnSave, gbc);
	    
	    JButton jBtnBack = new JButton("back");
	    gbc = setCons(2,0,1,1,0,0);
	    this.add(jBtnBack);
	    gbl.setConstraints(jBtnBack, gbc);
			
			
		GridBagLayout gbl2 = new GridBagLayout();
		JPanel jPanelGrid = new JPanel();
		//jPanelGrid.setLayout(gbl2);
		//jPanelGrid.setLayout(null);
		
		int count=12;
		//int count=32;
		
		jPanelGrid.setLayout(new GridLayout(count,count));
		
		JButton[] but = new JButton[count*count];
		
		for(int i=0;i<but.length;i++){
			but[i] = new JButton(String.valueOf(i));
			//but[i].setBounds(10*i, 10*i, 10, 10);
			but[i].setSize(10, 10);
			jPanelGrid.add(but[i]);
			
		}
		
		
				
		JScrollPane jScrollPaneGrid = new JScrollPane(jPanelGrid,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		gbc = setCons(0,1,3,1,0,1);
	    this.add(jScrollPaneGrid);
	    gbl.setConstraints(jScrollPaneGrid, gbc);
		
			
		this.setVisible(true);
	    
	    this.repaint();
	    

	}

	private String rekAlpha(double d){
		if(d/26>1){
			return rekAlpha(d/26) + (char)((d-1)%26+65);
		}
		return String.valueOf((char)((d-1)%26+65));
	}

		
  
}
 
Hallo guarditan,

versuch's mal so:

Java:
import java.awt.*;
import static java.awt.GridBagConstraints.*;
import javax.swing.*;

class Test extends JFrame {

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {

            public void run() {
                Test t = new Test();
                t.genWindowNewGrid();
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }

    public Test() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
        Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
        this.setBounds(screenInsets.left, screenInsets.top,
                screensize.width - screenInsets.left - screenInsets.right,
                screensize.height - screenInsets.top - screenInsets.bottom);
        this.setResizable(false);
        this.setUndecorated(false);
    }

    private GridBagConstraints setCons(int x, int y, int gx, int gy, double wx, double wy, int fill) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.gridwidth = gx;
        gbc.gridheight = gy;
        gbc.weightx = wx;
        gbc.weighty = wy;
        gbc.insets = new Insets(1, 1, 1, 1);
        gbc.fill = fill;
        return gbc;
    }

    private void genWindowNewGrid() {
        this.getContentPane().removeAll();
        this.setLayout(new GridBagLayout());
        String[] jcomboContent = {"right", "down", "column", "row"};
        JComboBox jcombo = new JComboBox(jcomboContent);
        this.add(jcombo, setCons(0, 0, 1, 1, 0, 0, NONE));
        JButton jBtnSave = new JButton("save");
        this.add(jBtnSave, setCons(1, 0, 1, 1, 0, 0, NONE));
        JButton jBtnBack = new JButton("back");
        this.add(jBtnBack, setCons(2, 0, 1, 1, 0, 0, NONE));
        JPanel jPanelGrid = new JPanel();
        int count = 32;
        jPanelGrid.setLayout(new GridBagLayout());
        JButton[] but = new JButton[count * count];
        int i = 0;
        for (int row = 0; row < count; row++) {
            for (int column = 0; column < count; column++) {
                but[i] = new JButton(String.valueOf(i));
                jPanelGrid.add(but[i], setCons(column, row, 1, 1, 0, 0, BOTH));
                i++;
            }
        }
        jPanelGrid.revalidate();
        JScrollPane jScrollPaneGrid = new JScrollPane(jPanelGrid,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        jScrollPaneGrid.setPreferredSize(new Dimension(702, 354));
        this.add(jScrollPaneGrid, setCons(0, 1, 3, 1, 1, 1, NONE));
        this.setVisible(true);
        this.repaint();
    }
}

Gruß,
André
 
Hi!

Ich hatte jetzt nur kurz reingeschaut und gesehen, dass du die PreferredSize bzw. MinimumSize nicht gesetzt hast.


Dieser Artikel Wie das GridBagLayout die Komponenten anordnet lässt mich vermuten folgendes vermuten:

Sobald der aktuelle Inhalt nicht mehr vollständig angezeigt werden kann - also die ScrollBars angezeigt werden müssen / aktiviert werden müssen - verwendet der LayoutManager die Preferred bzw. MinimumSize um die Größe des ScrollPane-Containers zu bestimmen.

Die ist aber - standardmäßig? - auf 22 X 22 eingestellt.

Hoffe das war a) soweit korrekt und b) es hilft

Grüße

Päddah
 
Hallo Päddah,

im vorliegenden Fall braucht man nur die PreferredSize vom jScrollPaneGrid zu setzen. Die PreferredSize vom jPanelGrid ergibt sich aus den impliziten PreferredSizes der JButtons, die dort untergebracht sind (dazu muss man allerdings das GridLayout für jPanelGrid durch GridBagLayout ersetzen).

Die MinimumSize wird hier nicht benutzt, da der Frame nicht resizable ist.

Gruß,
André
 
Danke an beide für eure Hilfen. Es funktioniert jetzt und nun kann ich mich endlich wieder dem Programmieren widmen und nicht mehr der Fehlersuche 🙂
 

Zurück
Oben