I'm trying To insert a JTable into a JScrollPane and I see a small gap between the borders of the table and the scroll Pane.And on the left side the table looks to be aligned to extreme left.Can someone please help me fix this.?
Removing setAutoResizeMode(JTable.AUTO_RESIZE_OFF) is fixing that.But I Need to turn that off.
this.dataTable = new SortableTable(this);
this.dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
this.dataTable.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
scrollPane = new JScrollPane(dataTable,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setPreferredSize(new Dimension(900,250));
scrollPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
You simply need to set the resize mode in a listener, when the component is resized. Here is an example:
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.table.TableColumn;
public class TableTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TableTest());
}
#Override
public void run() {
JTable table = new JTable(10, 3);
final JScrollPane scroller = new JScrollPane(table);
// update the resize mode when scroller is resized and window is shown
scroller.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
Window win = SwingUtilities.windowForComponent(scroller);
if (win != null && win.isVisible()) {
updateColumns(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
}
});
JFrame frm = new JFrame("Table");
frm.add(scroller);
frm.setSize(600, 400);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
// Transfer column widths from autoresize mode
private void updateColumns(JTable table) {
for (int i = 0; i < table.getColumnCount(); i++) {
TableColumn col = table.getColumnModel().getColumn(i);
col.setPreferredWidth(col.getWidth());
}
}
}
Related
I'm trying to make a grid of 20px x 20px buttons that I define as "cells", blank by default, no special decorations such as shading, and change color when clicked. (They are meant to show "1" just for testing purposes). I make a Cell class to define these buttons, give each an ActionListener.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Cell implements ActionListener
{
private JButton button;
private EditorPanel editorPanel;
public Cell(EditorPanel editorPanel){
button = new JButton("1'");
button.addActionListener(listener -> colorCell());
button.setPreferredSize(new Dimension(20,20));
button.setMargin(new Insets(0,0,0,0));
button.setOpaque(true);
button.setContentAreaFilled(false);
this.editorPanel = editorPanel;
}
public JButton getButton() {
return button;
}
public void colorCell()
{
button.setBackground(Color.BLACK);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
and then use an array of Cell objects (cells) in my EditorPanel class to create a grid of these buttons with dimensions defined by "col" and "row".
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class EditorPanel{
public JFrame jframe;
public JPanel jpanel;
public static EditorPanel editorPanel;
public Render render;
public static final int col = 45, row = 45, tile_size=20;
public static final int panelWidth=900, panelHeight=900;
public Dimension dim;
public int coloredPixels;
public Cell[][] cells;
public void getFrame() {
editorPanel = new EditorPanel();
dim = Toolkit.getDefaultToolkit().getScreenSize();
jframe = new JFrame("Pixel Art Creator");
jframe.setVisible(true);
jframe.setSize(panelWidth+17, panelHeight+40);
jframe.setLocation(dim.width/2 - jframe.getWidth()/2, dim.height/2 - jframe.getHeight()/2);
jframe.add(render = new Render());
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JPanel addCells()
{
cells=new Cell[row][col];
JPanel panel = new JPanel(new GridLayout(row, col));
for(int i = 0; i< row; i++){
for(int j = 0; j<col; j++){
cells[i][j] = new Cell(this);
panel.add(cells[i][j].getButton());
}
}
return panel;
}
public static void main (String[] args)
{
editorPanel = new EditorPanel();
editorPanel.getFrame();
editorPanel.addCells();
}
}
I then try to add each created Cell object that I attempted to put into the cells array in the addCells() method and add it to my JPanel. When I run this code I don't get any buttons, meaning that these buttons aren't being added to JPanel. How should I go about this?
So, two "significant" issues:
editorPanel.addCells(); never adds the JPanel that it creates to anything, so it will never be displayed
Calling JFrame#setVisible BEFORE you've finished establishing the UI can cause the UI elements not to show up on the UI. You can fix this by calling revalidate and repaint on the container which is changed, but if possible, simply get the UI established first, then make it visible
I would, however, suggest a slight change in approach. Rather then making Cell a class which contains a JButton, and then exposing that button to other aspects of your UI, I would make Cell a component and simply add it to the what ever container you want, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int y = 0; y < 20; y++) {
gbc.gridy = y;
for (int x = 0; x < 20; x++) {
gbc.gridx = x;
add(new Cell(), gbc);
}
}
}
}
public class Cell extends JPanel {
public Cell() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
colorCell();
}
});
setBorder(new LineBorder(Color.GRAY));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(20, 20);
}
protected void colorCell() {
if (getBackground() != Color.DARK_GRAY) {
setBackground(Color.DARK_GRAY);
} else {
setBackground(null);
}
}
}
}
Now, I've just used a plain old JPanel in the this case, but you could just as easily extend from a JButton or JToggledButton ... but I might be tempted to use a factory pattern instead, but that's me.
The purpose of using a GridBagLayout is to allow the frame and outer containers to be resized without changing the size of the Cells themselves, unlike GridLayout, which will try and make the cells fill the available space
I have an application with a few tables and a white application background to blend in with used logos. I have set all the backgrounds to white but there is one space that I could not reach so far.
With the standard JTable I am using it is possible to move columns and this is totally fine. However when moving the columns you are still able to see the standard applications color behind the TableHeaders. As displaying in a JScrollPane I thought setting the background of the ScrollPane.getContentHeader() would help but I get an NPE.
Below is a small program that should display the problem:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
String[] columns = new String[] { "ABC", "DEF", "XYZ" };
TableModel tm = new DefaultTableModel(columns, 3);
table = new JTable();
table.setModel(tm);
table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
scrollPane.setViewportView(table);
}
}
When moving one of the three columns you will notice the standard background of your LAF (for me it is the Standard Windows LAF with its beige like color) instead of white eventhough the background of the TableHeader is set to white.
The color is set as well for the parts of the scrollPane width where no tableheaders are displayed and sets the color of the header to the correct color but I cannot figure out how to do so for the space behind the headers.
EDIT: After this seems to get misunderstood, I made a screen of my problem:
Unfortunately you cannot see the cursor, but I am holding the column at its header and dragging it to the right.
your problem are based on code line (because I think that JTable aren't designated to be non_resizable, maybe this is bug maybe its feature)
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
you can to override this painting artefact by, then override the desired Color in Renderer
table.getTableHeader().setBackground(scrollPane.getBackground());
I'd be use JTable.AUTO_RESIZE_OFF, in most case there isn't reason to be restricted to fixed size, my view is to use LayoutManager in all cases, without any restriction(s), e.g.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
//http://stackoverflow.com/questions/40969405/change-background-behind-jtable-tableheaders
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JScrollPane scrollPane = new JScrollPane();
private String[] columns = new String[]{"ABC", "DEF", "XYZ"};
private TableModel tm = new DefaultTableModel(columns, 3);
private JTable table = new JTable(tm);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
testsforSO frame = new testsforSO();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
String[] columns = new String[]{"ABC", "DEF", "XYZ"};
TableModel tm = new DefaultTableModel(columns, 3);
table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.getTableHeader().setBackground(scrollPane.getBackground());
table.getTableHeader().setOpaque(true);
table.setFillsViewportHeight(true);
//table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
scrollPane.setViewportView(table);
add(scrollPane);
}
}
EDIT
Try your program you gave as an answer (including scrollPane.getViewport().setBackground(Color.BLACK);) and run it. Black shows the problem better.
to see
from code (again to use Renderer for painting the Color inside JTables view)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
//http://stackoverflow.com/questions/40969405/change-background-behind-jtable-tableheaders
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JScrollPane scrollPane = new JScrollPane();
private String[] columns = new String[]{"ABC", "DEF", "XYZ"};
private TableModel tm = new DefaultTableModel(columns, 3);
private JTable table = new JTable(tm);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
testsforSO frame = new testsforSO();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
String[] columns = new String[]{"ABC", "DEF", "XYZ"};
TableModel tm = new DefaultTableModel(columns, 3);
//table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.getTableHeader().setBackground(Color.BLACK);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setBackground(Color.BLACK);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
scrollPane.getViewport().setBackground(Color.BLACK);
scrollPane.setViewportView(table);
add(scrollPane);
}
}
none of them worked, where the last one brings up an NPE.
The table header is not actually added to the frame until the frame is visible. At this time the scrollpane will get the table header from the table and add the header to the column header of the scrollpane.
So, AFTER the frame is visible you can do:
JTableHeader header = table.getTableHeader();
header.getParent().setBackground(Color.YELLOW);
So the above is required in addition to setting the four levels as suggested by #mKorbel.
You can also check out: Setting JTableHeader holder background colour for a more detailed answer.
I saw the BallonTip at java.net and I tried to integrate it into my application to be displayed when a user clicks a table cell. When a table cell is clicked, the BalloonTip is showing up as intended, but when you scroll it out of the current viewport, you can click another cell without the BalloonTip showing up. When you scroll the table, the BallonTip is shown again.
Here is an example:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.java.balloontip.BalloonTip;
import net.java.balloontip.TablecellBalloonTip;
import net.java.balloontip.styles.EdgedBalloonStyle;
public class TableTest2 extends JFrame {
static final int LENGTH = 40;
TablecellBalloonTip tip;
JTable mainTable;
JPanel main;
JLayeredPane layeredPane;
JScrollPane mainScroll;
TableTest2() {
mainTable = new JTable(LENGTH, LENGTH);
CustomListSelectionListener clsl = new CustomListSelectionListener(mainTable);
mainTable.getColumnModel().getSelectionModel().addListSelectionListener(clsl);
mainTable.getSelectionModel().addListSelectionListener(clsl);
mainTable.setTableHeader(null);
mainTable.setColumnSelectionAllowed(true);
mainScroll = new JScrollPane(mainTable);
add(mainScroll);
tip = new TablecellBalloonTip(mainTable, new JLabel("Hello World!"), -1, -1, new EdgedBalloonStyle(Color.WHITE,
Color.BLUE), BalloonTip.Orientation.LEFT_ABOVE, BalloonTip.AttachLocation.ALIGNED, 5, 5, false);
setPreferredSize(new Dimension(500, 400));
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
public static void main(String[] args) {
new TableTest2();
}
protected class CustomListSelectionListener implements ListSelectionListener {
private int row, column, lead, anchor;
private JTable table;
public CustomListSelectionListener(JTable table) {
this.table = table;
}
#Override
public void valueChanged(ListSelectionEvent evt) {
if (evt.getSource() == table.getSelectionModel() && table.getRowSelectionAllowed()) {
// row selection changed
row = table.getSelectedRow();
column = table.getSelectedColumn();
tip.setCellPosition(row, column);
tip.refreshLocation();
} else if (evt.getSource() == table.getColumnModel().getSelectionModel()
&& table.getColumnSelectionAllowed()) {
// column selection changed
lead = table.getColumnModel().getSelectionModel().getLeadSelectionIndex();
anchor = table.getColumnModel().getSelectionModel().getAnchorSelectionIndex();
if (lead <= anchor) {
column = anchor;
} else {
column = lead;
}
row = table.getSelectedRow();
tip.setCellPosition(row, column);
tip.refreshLocation();
}
}
}
}
How can I force the BalloonTip to be shown after I click a cell in the table? I think there is a listener, which is listening for the scrolling event and manages the painting of the BallonTip, but I do not have a clue which one it is.
best regards
htz
According to this mailing list, there was a bug in the BallonTip version 1.2.1. Now, with version 1.2.3, this is fixed.
just looking for a quick answer: is it possible to use a JTable as a JScrollPane's columnHeader?
I have a configed JTable with different column width and column title, and plan to use the header as the columnHeader of a scrollpane. How can I achieve this? I set the table with
scrollPane.setColumnHeaderView(table);
but it doesn't show up.
so thanks to Guillaume Polet, it should be
scrollpane.setColumnHeaderView(table.getTableHeader());
but all the columns have the same width now although I set them with different values in my table. How could I let the table columns show different width?
If I understand you correctly, you want the column headers of your table to appear in the column headers of the viewport but you want something else in the viewport view?
Then you need to grab the table header and set it as the column header of the viewport.
Here is an example:
import java.awt.BorderLayout;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestTableHeader {
protected void initUI() {
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
Vector<String> colNames = new Vector<String>();
for (int i = 0; i < 5; i++) {
colNames.add("Col-" + (i + 1));
}
table = new JTable(data, colNames);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
scrollpane = new JScrollPane();
scrollpane.setColumnHeaderView(table.getTableHeader());
scrollpane.setViewportView(new JLabel("some label in the viewport view"));
frame.add(scrollpane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JTable table;
private JScrollPane scrollpane;
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTableHeader().initUI();
}
});
}
}
Hi I want to put my button at the South position! How can I do that? Here is my code:
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.*;
import java.util.*;
import javax.swing.JButton;
public class TableDemo extends JPanel {
private static Icon leftButtonIcon;
private boolean DEBUG = false;
// added static infront becuase got non static referencing error
static List<String[]> rosterList = new ArrayList<String[]>();
public TableDemo() {
super(new GridLayout(1,0));
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
JButton button=new JButton("Buy it");
button.setSize(30,60);
button.add(button);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane);
//create a button
}
class MyTableModel extends AbstractTableModel {
private String[] columnNames = { "Κωδικός", "Ποσότητα", "Τιμή", "Περιγραφή", "Μέγεθος", "Ράτσα"};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return rosterList.size();
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return rosterList.get(row)[col];
}
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TableDemo newContentPane = new TableDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
Something like this?
See the comments in the code.
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.border.EmptyBorder;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.io.*;
import java.util.*;
import javax.swing.JButton;
public class TableDemo extends JPanel {
private static Icon leftButtonIcon;
private boolean DEBUG = false;
// added static infront becuase got non static referencing error
static List<String[]> rosterList = new ArrayList<String[]>();
public TableDemo() {
super(new BorderLayout(3,3));
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
JButton button=new JButton("Buy it");
// Rarely has the intended effect.
// also best not to presume we can guess the size
// a component needs to be.
//button.setSize(30,60);
// cannot add a button to itself!
//button.add(button);
JPanel buttonCenter = new JPanel( new FlowLayout(FlowLayout.CENTER) );
// allow the button to be centered in buttonCenter,
// rather than stretch across the width of the SOUTH
// of the TableDemo
buttonCenter.add(button);
add(buttonCenter, BorderLayout.SOUTH);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane, BorderLayout.CENTER);
//create a button
// add a nice border
setBorder(new EmptyBorder(5,5,5,5));
}
class MyTableModel extends AbstractTableModel {
// apologies about the column names
private String[] columnNames = { "??d????", "??s?t?ta", "??µ?", "?e????af?", "???e???", "??tsa"};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return rosterList.size();
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return rosterList.get(row)[col];
}
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TableDemo newContentPane = new TableDemo();
// JPanels are opaque by default!
//newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Should be done on the EDT.
// Left as an exercise for the reader.
TableDemo.createAndShowGUI();
}
}
You add the button to itself, and you should use BorderLayout, if you want to place the components in Center / North / South / etc. manners:
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
"Hi i want to put my button at the South posotion! how can i?"
If you want to place something in a BorderLayout location, it would make sense to have the container use a ... BorderLayout, n'est-ce pas?
But seriously, most of your recent questions in this forum suggest you're coming here before reading the tutorials. You've already been given the links several times, so please do yourself a favor and learn Swing right -- study the layout tutorials and other tutorials and you will save yourself a lot of grief and guessing.
try this:
JFrame frame = new JFrame();
frame.add(yourbutton,BORDERLAYOUT.SOUTH)
and for give position and size to button,do this
yourbutton.setBounds(10,15,120,200) --> (x,y,height,width) , x , y set possition