I'm making an application in eclipse with swing and jfreechart and I have the following problem:
As you can see in the screenshot I have a frame with a few components. The problem is about the JTable, which always has the same size, no matter if I resize the window. I want the table to resize the same way other components do, like the ChartPanel at the right, and I don't know how to do it. The contentPane has a BorderLayout with three panels:
The scrollPane for the JTable (WEST)
The ChartPanel (CENTER)
The panel for the buttons (SOUTH)
The code for the JTable creation is this:
private JTable getTasksTable() {
if (tasksTable == null) {
tasksTable = new JTable(new DefaultTableModel(new Object[] { "ID", "Duration", "Due-Date" }, 0) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
});
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
for (int i = 0; i < tasksTable.getColumnModel().getColumnCount(); i++) {
tasksTable.getColumnModel().getColumn(i).setCellRenderer(centerRenderer);
}
tasksTable.getTableHeader().setDefaultRenderer(centerRenderer);
tasksTable.getTableHeader().setBorder(new LineBorder(new Color(0, 0, 0)));
tasksTable.setBorder(new LineBorder(new Color(0, 0, 0)));
tasksTable.setFillsViewportHeight(true);
}
return tasksTable;
}
The scrollPane for the JTable (WEST), The ChartPanel (CENTER), The panel for the buttons (SOUTH)
Well, the way a BorderLayout works is that:
the components in the WEST/EAST are sized at the preferred width of the component.
The component in the CENTER gets the remaining width.
So in your case the scrollpane is a fixed width and the width of the chart panel varies.
If you want both the scrollpane and the chart panel width to change as the frame size changes you need to use a different layout manager.
In this case you could use a panel with a GridBagLayout for the scrollpane and chart components. Then GridBagLayout will assign space at the preferred size of each component. Then you can specify the weightx constraint for each component to specify what percentage of extra space goes to each component as the frame with is increased.
Read the section from the Swing tutorial on How to Use GridBagLayout for more information on the constraints and working examples to get you started.
Related
I have Googled for hours on this issue but nothing seems to work.
I have a JTable with a JPanel inside a frame. The table has data from a database but there is a considerable amount of data to store (hence require the JScrollPane)
Here is my code:
public GeneralDisplay()
{
Insets insets = getInsets();
panel = new JPanel();
scrollVert = new JScrollPane(panel);
scrollVert.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollHor = new JScrollPane(panel);
scrollHor.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
newSoftwareBtn = new JButton("New");
removeSofwtareBtn = new JButton("Remove");
editSofwtareBtn = new JButton("Edit");
ResultSet results;
try
{
results = statement.executeQuery("SELECT * FROM Software");
cSoftware = new JTable(buildTableModel(results));
}
catch(SQLException sqlEx)
{
JOptionPane.showMessageDialog(null, "Error: SQL error!");
//System.exit(1);
}
///////////////////////////////////////////////////
//Adding to form
///////////////////////////////////////////////////
getContentPane().add(panel);
cSoftware.setBackground(null);
cSoftware.getTableHeader().setBackground(null);
//pack();
panel.add(scrollVert);
panel.add(scrollHor);
panel.add(cSoftware.getTableHeader());
panel.add(cSoftware);
panel.add(newSoftwareBtn);
panel.add(removeSofwtareBtn);
panel.add(editSofwtareBtn);
panel.add(scrollVert);
panel.add(scrollHor);
panel.revalidate();
panel.repaint();
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//Position on form
//////////////////////////////////////////////////////
Dimension size = newSoftwareBtn.getPreferredSize();
newSoftwareBtn.setBounds(5 + insets.left, 480 + insets.top, size.width, size.height);
size = removeSofwtareBtn.getPreferredSize();
removeSofwtareBtn.setBounds(55 + insets.left, 480 + insets.top, size.width, size.height);
size = editSofwtareBtn.getPreferredSize();
editSofwtareBtn.setBounds(105 + insets.left, 480 + insets.top, size.width, size.height);
In the image, the JScrollPane is visible in the area marked with a red square. I have more data in the table which is not visible, which is why I thought to add the JScrollPane to the table, but I also have buttons on my panel below the table which is why I wanted to add it to the panel.
My code might not be great as I have followed several tutorials on how to overcome the problem and kind of mashed them together.
Any help appreciated!
EDIT:
I have noticed that I added my scrolls to the panel twice. I have now removed that but still did not resolve the issue if that's what you thought it was
The other image is what happened when I added a GridLayout to the panel
Firstly, you don't need to create two JScrollPanes in order to have both a vertical and a horizontal scrollbar.
As far as the ScrollPane being seperated from the rest of your components, you need to add your JTable to the ScrollPane and then add that to the JPanel. Something like this:
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.add(cSoftware);
panel.add(scrollPane);
//add buttons etc
In your original code, you added both your (empty) ScrollPanels as well as your table to the JPanel.
I think you confuse a JScrollPane for a JScrollBar:
A JScrollPane is a wrapper to which you add large content, and which will show JScrollBar (either vertical or horizontal, or both) when this content exceeds the size of the container.
A JScrollBar is the actual horizontal or vertical scroll bar that you click and scroll.
In general you should work with a JScrollPane and let it take care of the scroll bars for you.
Based on the above, the answer to your question is:
Add the JTable to the JScrollPane (new JScrollPane(table);). You need only one JScrollPane in your situation.
Add the JScrollPane to the JPanel (To which you can also add your buttons)
Add the JPanel to the JFrame
Additionally:
You should use layout managers (By default, a JPanel has a FlowLayout, which might not be very convenient).
You don't need to add your table and your table's header separately.
You don't need to use repaint() or revalidate()
How do i put Jlabel and Jtext in the same frame?
if i add the text last, then only the text are showen, thes is my code:
public MatrixFrame(String framname, int width, int height) {
width =7;
height = 6;
JFrame fram = new JFrame(framname);
fram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fram.setSize(500,500);
JTextArea text = new JTextArea("Here come Text");
valMatrixPanel = new ValMatrixPanel(height,width,Color.GRAY, Color.black);
JPanel pan = valMatrixPanel.getPan(); // pan is 6*7 panels lock the picture
fram.add(pan);
fram.add(text);
fram.setVisible(true);
}
}
The key to solving this is your understanding how to use layout managers, because this is how Swing decides where to put what and how to size things. First off for a quick easy fix, put all your components into a JPanel, which uses a FlowLayout by default, and then add the JPanel to your JFrame. Don't set the JPanel's or the JFrame's size, do call pack() on the JFrame after adding everything and then finally call setVisible(true).
The better long term answer: read the layout manager tutorials which you can find, among the other Swing tutorials: here.
Try this
you will have to add a import for grid layout
check that
all you need to do is add a grid layout because the textbox overlaps the panel.
so add the line
fame.getContentPane().setLayout(new GridLayout(1,1));
JPanel pan = valMatrixPanel.getPan(); // pan is 6*7 panels lock the picture
fame.getContentPane().setLayout(new GridLayout(1,1));
fram.add(pan);
fram.add(text);
fram.setVisible(true);
use BorderLayout in fram.add()
like this
public MatrixFrame(String framname, int width, int height) {
width =7;
height = 6;
JFrame fram = new JFrame(framname);
fram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fram.setSize(500,500);
JTextArea text = new JTextArea("Here come Text");
valMatrixPanel = new ValMatrixPanel(height,width,Color.GRAY, Color.black);
JPanel pan = valMatrixPanel.getPan(); // pan is 6*7 panels lock the picture
fram.add(pan,BorderLayout.WEST);
fram.add(text,BorderLayout.NORTH);
fram.setVisible(true);
}
I am currently trying to create a script editor. But the lineNumber JPanel is not top aligned next to the JTextArea. The lineNumber JPanel appears at the center on the right side of the JTextArea.
It looks like this:
This is the class which instantiates both of these components:
private ScriptEditor() {
((FlowLayout) this.getLayout()).setVgap(0);
((FlowLayout) this.getLayout()).setHgap(0);
//This is the lineNumber JPanel which has no LayoutManager set.
lineNumPanel = new LineNumberPanel();
//I tried setAlignmentY but it did not work
lineNumPanel.setAlignmentY(TOP_ALIGNMENT);
//The text area.
scriptArea = new JTextArea(22,15);
scriptArea.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 15));
scriptArea.setMargin(new Insets(3, 10, 3, 10));
//This JPanel contains the two components: lineNumber JPanel and the JTextArea
JPanel temp = new JPanel();
temp.add(lineNumPanel);
temp.add(scriptArea);
//Set the scrollPane
JScrollPane scrollPane = new JScrollPane(temp);
scrollPane.setPreferredSize(new Dimension(width, height));
//Add the scrollPane to this JPanel.
add(scrollPane);
}
JPanel temp = new JPanel();
By default a JPanel uses a FlowLayout. a FlowLayout vertically centers the components added to the panel. If you don't like this behaviour then try a different layout manager like a horizontal BoxLayout, which will allow you to align the component at the top/center/bottom depending on the components vertical alignment.
However, using a JPanel is not the best approach. Instead you should be adding the line number component to the row header of the scroll pane. See Text Component Line Number for an example of this approach.
Currently I have a nifty JViewport with a Jlabel set up and used as a view. I'm wondering if it's possible to use layered Jlabels as the Viewport's view. IE: I want to add new JLabels into a pre-existing Viewport.
Thanks!
EDIT: On StanislavL's advice, I'm now using a JLayeredPane within an JScrollPane. Currently there are two JLabels in the JLayeredPane, when I scroll the JScrollPane, the larger background image scrolls properly, by the smaller shipSprite remains in the same position. Any ideas how I can get them to scroll together?
public void initViewport() {
explorePort = new JScrollPane();
explorePort.setBounds(0, 0, retailWidth, retailHeight);
explorePort.setBackground(new Color(0, 100, 0));
explorePort.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
explorePort.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
ImageIcon background = Main.global.imgScaler.scaleImage(new ImageIcon("images/blankgrid.jpg"), retailWidth*2, retailHeight*2);
JLabel backSplash = new JLabel(background);
backSplash.setBounds(0, 0, retailWidth*2, retailHeight*2);
ImageIcon shipIcon = Main.global.imgScaler.scaleImage(new ImageIcon("images/ship.png"), Main.global.nodeWidth, Main.global.nodeHeight);
JLabel shipSprite = new JLabel(shipIcon);
shipSprite.setBounds(100, 100, Main.global.nodeWidth, Main.global.nodeHeight);
Main.global.gamePanel.add(backSplash, 0);
explorePort.setViewportView(backSplash);
Main.global.gamePanel.add(shipSprite, 1);
Main.global.gamePanel.add(explorePort, 2);
//explorePort.addMouseListener(this);
Main.global.gameFrame.addKeyListener(new ListenKey());
}
Use Layered pane to add multiple lables to container and place the container in JScrollPane
http://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html
This code puts a JTable into a JFrame (sole component of the whole UI):
JFrame frame = new JFrame( "Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable table = appender.createTable();
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
I also have some code to set the preferred size of the columns.
Nothing fancy. When the UI opens, the table takes up the whole view and I have no scroll bars. The combined preferred widths of the columns need more horizontal space than the windows is wide. Despite of that, there is no horizontal scroll bar and the columns are too narrow.
What do I have to do that
The columns are still resizable by the user
The current width is respected? I.e. when I change the width of one column, the width of the other columns should not change.
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
You can also add the scrollpane containing the table to a JPanel and then add the panel to the frame. That way the panel will change in size, not the scrollpane.