Trying to get two dimensional Array in JTable in JScrollPanel Java - java

My plan is to get a 2-dimensional array into a JTable into a JScrollPanel. The Table already shows the 2-dimensional array's data. The problem is that the table won't show when I add it to a jscrollpanel (The scrollpanel is visible though but empty. It does work when I put the table in the JPanel (not jscrollpanel). but not when using a jscrollpanel.
Does any one have any idea?
package arraytablestable;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class ArrayTablesTable extends JFrame {
public static JFrame frame;
public static void main(String[] args) {
frame = new JFrame();
frame.setSize(1280,720);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Array Table 7 in Tables");
frame.setContentPane(new Paneel());
frame.setVisible(true);
}
private static class Paneel extends JPanel {
// Declareren
public static JTable Table;
public JTableHeader tblHeader;
public TableModel tblModel;
public Object[] columnNames;
public static Object[][] Data;
public int Resultaat, a ,i ;
public JScrollPane jScrollPane;
public Paneel() {
this.setLayout(new GridLayout(1,1));
// Initialiseren
Data = new Object[200][1];
columnNames = new Object[]{"Product","Resultaat"};
// Model maken & importen
tblModel = new DefaultTableModel(columnNames,0);
Table = new JTable(tblModel);
// Table Eigenschaooen
// tblHeader = Table.getTableHeader();
// tblHeader.setBackground(Color.decode("#a181a1"));
// tblHeader.setForeground(Color.decode("#1b1b1b"));
// Table.setFocusable(false);
// Table.setRowSelectionAllowed(false);
Data[0] = new String[100];
Data[1] = new Integer[100];
// For Loop
for(i = 0; i < 100; i++){
Data[0][i]= "7 x " + i;
Resultaat = 7 * i;
Data[1][i]= Resultaat;
TabelVullen(new Object[]{Data[0][i],Data[1][i]});
}
System.out.println("object: " + Data[0][4]);
this.add(jScrollPane);
}
public void TabelVullen(Object[] data){
((DefaultTableModel)Table.getModel()).addRow(data);
// Components -> Panel
jScrollPane = new JScrollPane(Table);
jScrollPane.add(Table);
}
}
}

jScrollPane = new JScrollPane(Table);
The above line is correct. It creates the scrollpane and adds the table to the "viewport" of the scrollpane.
//jScrollPane.add(Table);
The above line is incorrect. It removes the table from the viewport of the scrollpane. Never use the add(...) method of a scrollpane. All components must be added to the viewport.
Learn of follow Java naming conventions. Variable names should NOT start with an upper case character. "Table" should be "table". All you other names follow this standard. Be consistent!!!
Also, method names should NOT start with an upper case character (TabelVullen).

Related

GridLayout is showing odd behavior

I am trying to create a grid comprised of 100 squares. My code below is extremely buggy and I am not sure why.
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
public class snake extends JFrame
{
public static void main(String[] args)
{
Border whiteLine = BorderFactory.createLineBorder(Color.white);
//-----------FRAME
JFrame frame = new JFrame();
frame.setSize(1000,1000);
frame.setTitle("Snake");
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.black);
frame.setVisible(true);
frame.setLayout(new GridLayout(10,10));
//-----------FRAME
//-----------PANELS
Dimension panelDimension = new Dimension(20,20);
int counter = 0;
JPanel[][] p = new JPanel[10][10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
p[i][j] = new JPanel();
//p[i][j].setPreferredSize(panelDimension);
p[i][j].setBackground(Color.red);
//p[i][j].setLocation(490,490);
p[i][j].setBorder(whiteLine);
p[i][j].setVisible(true);
frame.getContentPane().add(p[i][j]);
counter+=1;
}
}
System.out.println("counter: " + counter);
}
}
When I run the code like this it shows a grid comprised of 2 columns the first column has 7 rows and the second column has 6. Sometimes it even shows other incorrect numbers of columns and rows. I am not sure why it doesn't create a grid of 10 rows 10 columns.
You've got several problems including:
Calling setVisible(true) on the JFrame before adding components, before calling pack() on the top-level window. This can lead to wonky positioned components within our GUI's or even GUI's that remain empty
Not calling pack() on the JFrame after adding components and before setting it visible
Setting the size of the JFrame. Let the layout managers, containers and components do this for you (which is what calling pack() is for)
Setting it to a bad size, a "perfect square", one that ignores the menu bar that the OS adds,
...
For example:
package foo01;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SnakePanel extends JPanel {
private static final int CELL_WIDTH = 80;
private static final Dimension CELL_DIMENSION = new Dimension(CELL_WIDTH, CELL_WIDTH);
private static final int COLUMNS = 10;
private static final int GAP = 2;
private static final Color BG_COLOR = Color.WHITE;
private static final Color CELL_COLOR = Color.RED;
public SnakePanel() {
setBackground(BG_COLOR);
// add a white line around the grid
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
// create a grid with gaps that show the background (white) color
setLayout(new GridLayout(COLUMNS, COLUMNS, GAP, GAP));
for (int row = 0; row < COLUMNS; row++) {
for (int col = 0; col < COLUMNS; col++) {
JPanel cell = new JPanel(); // create a new cell
cell.setPreferredSize(CELL_DIMENSION); // cheating here. Better to override getPreferredSize()
cell.setBackground(CELL_COLOR);
add(cell);
// give the cell JPanel some simple behavior:
cell.addMouseListener(new MyMouse(col, row));
}
}
}
private class MyMouse extends MouseAdapter {
private int col;
private int row;
public MyMouse(int col, int row) {
this.col = col;
this.row = row;
}
#Override
public void mousePressed(MouseEvent e) {
System.out.printf("Mouse pressed row and column: [%d, %d]%n", row, col);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
// create the main JPanel
SnakePanel snakePanel = new SnakePanel();
// create the JFrame
JFrame frame = new JFrame("Snake");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// add the main JPanel to the JFrame
frame.add(snakePanel);
// pack the JFrame -- tells the layout managers to do their things
frame.pack();
// if we want to center the GUI:
frame.setLocationRelativeTo(null);
// only *now* do we display the GUI
frame.setVisible(true);
});
}
}
Some notes on the code:
Any code within the Runnable passed into the SwingUtilities.invokeLater(...) method is called on the Swing event thread, which is a wise thing to do when creating a Swing GUI
SwingUtilities.invokeLater(() -> {
// ....
});
First, create the main JPanel that is held by the JFrame:
SnakePanel snakePanel = new SnakePanel();
Then create the JFrame, add that JPanel and call pack(). The pack call tells the layout managers to do there thing, to lay out components within containers, to size things based on their preferred sizes and their layouts:
JFrame frame = new JFrame("Snake");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(snakePanel);
frame.pack();
if we want to center the GUI:
frame.setLocationRelativeTo(null);
only now do we display the GUI
frame.setVisible(true);

Java Swing one-row scrollable container?

I'm writing an app, that needs some kind of one-row JList to store formula objects. I first tried with just buttons as objects with text on them, but it was not good. Then I made one-row JList but all it's cells have the same width, and it looks like this
(a scrollable area). So "<" will have the same width as others and it looks bad.
Is there a way to force list cells to use their real width? Or there is any cool container that just can store objects(just text) with scrolling over them?
With buttons it looks like
How about you use the JTable which you can configure it to have a single row?
Example Code:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class JTableTest {
JFrame f;
JTable j;
JTableTest()
{
f = new JFrame();
f.setTitle("JTable Example");
String[][] data = {
{ "F=ma", "e=mc^2", "a^2=b^2+c^2" }
};
String[] columnNames = { "Newton", "Einstein", "Pythagoras" };
j = new JTable(data, columnNames);
j.setBounds(30, 40, 200, 300); //Position x,y & Size of JTable height,width
JScrollPane sp = new JScrollPane(j);
f.add(sp);
f.setSize(500, 200);
f.setVisible(true);
}
public static void main(String[] args)
{
new JTableTest();
}
}
By default, the width of JTable cells are fixed. You can change them, however, using:
j.getColumnModel().getColumn(0).setPreferredWidth(5); //Set Width=5 for first column

placing 64 buttons randomly in a girdlaout java

The goal is to create a create a game like rubrics cube where the user has to rearrange the buttons according to the matched color. This is what I did to place the buttons randomly, but it doesn't work when the buttons are presented. The random order is taken as the ordered order if that makes sense. Any ideas on how to fix this?
while(list1.size()!=501){
int x=rand.nextInt(8);
list1.add(x);
}
while(list2.size()!=501){
int x=rand.nextInt(8);
list2.add(x);
}
for(int b=0;b<500;b++){
int l= list1.get(b);
//System.out.println(l);
int j= list2.get(b);
panel.add(buttons[l][j]);
//System.out.println(buttons[l][j].getBackground());
}
Consider:
Giving the buttons a value of some sort that represents their true order. There are several ways to do this, including putting them in an array of specified order, or extending JButton and giving your class an int value field, or using a HashMap
Place these buttons into an ArrayList<JButton>
Shuffling the ArrayList via Collections.shuffle(...)
Then adding the buttons to your GUI
Alternatively, you could use non-shuffled JButtons and instead shuffle AbstractActions which you then set into the buttons.
The details of any solution will depend on the details of your current program, something that we don't yet know enough about. If you need more detailed help, do consider creating and posting a valid MCVE in your question.
For example, compile and run this, and then read the comments:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.*;
public class RandomButtons extends JPanel {
private static final long serialVersionUID = 1L;
private static final int ROWS = 8;
private JButton[][] buttons = new JButton[ROWS][ROWS];
private List<JButton> buttonList = new ArrayList<>();
private JPanel buttonsPanel = new JPanel(new GridLayout(ROWS, ROWS));
public RandomButtons() {
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons[i].length; j++) {
// create new JBUtton
final JButton button = new JButton("Button");
// put into array
buttons[i][j] = button;
// put into ArrayList
buttonList.add(button);
// unique value 0 to 63 for each button
// order it has been created
final int value = i * ROWS + j;
// create one of 64 different color hues using value above
float hue = ((float) value) / (ROWS * ROWS);
float sat = 0.7f; // reduce sat so we can see text
float brightness = 1.0f;
Color color = Color.getHSBColor(hue, sat, brightness);
button.setBackground(color); // set button's color
button.addActionListener(e -> {
// display the button's order
System.out.println("Value: " + value);
});
}
}
randomizeButtons();
JButton randomizeButton = new JButton("Randomize");
randomizeButton.addActionListener(e -> { randomizeButtons(); });
JButton orderButton = new JButton("Put in Order");
orderButton.addActionListener(e -> { orderButtons(); });
JPanel bottomPanel = new JPanel(new GridLayout(1, 2));
bottomPanel.add(randomizeButton);
bottomPanel.add(orderButton);
setLayout(new BorderLayout());
add(buttonsPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
public void randomizeButtons() {
buttonsPanel.removeAll(); // remove all buttons
Collections.shuffle(buttonList); // shuffle the ArrayList
// re-add the buttons **using the ArrayList**
for (JButton jButton : buttonList) {
buttonsPanel.add(jButton);
}
// tell JPanel to layout its newly added components
buttonsPanel.revalidate();
// and then paint them
buttonsPanel.repaint();
}
public void orderButtons() {
buttonsPanel.removeAll(); // remove all buttons
// re-add the buttons **using the 2D array**
for (JButton[] buttonRow : buttons) {
for (JButton jButton : buttonRow) {
buttonsPanel.add(jButton);
}
}
buttonsPanel.revalidate();
buttonsPanel.repaint();
}
private static void createAndShowGui() {
RandomButtons mainPanel = new RandomButtons();
JFrame frame = new JFrame("RandomButtons");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

Howto setup JTable growth from bottom to top

I'm looking for a way to fill JTable from bottom to top, for example:
1 row:
[clean space]
row1
after adding 2nd row:
[clean space]
row2
row1
Looked at ComponentOrientation - seems it allows only right-to-left but not bottom-to-up
Also don't see any ways by using LookAndFill
Any ideas?
I found a solution, thank you guys!
It's pretty simple by extracting table header to BorderLayout.NORTH and adding table entries to BorderLayout.SOUTH. This allows to make table growing from bottom to top.
Table entries can further be reversed by entries decorator by this way.
Code snippet below:
final MyTableModel model = new ReverseOrderModelDecorator(new MyTableModel());
final JTable table = new JTable(model);
JTableHeader header = table.getTableHeader();
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(header, BorderLayout.NORTH);
mainPanel.add(table, BorderLayout.SOUTH);
thank you guys!
I hope this is the behaviour you are looking for:
import java.awt.ScrollPane;
import java.util.Collections;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
/**
*
* #author Skynet
*/
public class JTableReverseFill {
public static void main(String[] args) {
Runnable r = new Runnable(){
#Override
public void run() {
JFrame frame = new JFrame("jtable-reverse");
frame.setSize(200,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable jt = new JTable();
MyReversedTableModel mtm = new MyReversedTableModel();
mtm.addColumn("col1");
mtm.addColumn("col2");
for(Integer i = 0; i < 1000; i++)
{
mtm.addRow(new Object[]{"cell" + i.toString(), "cell" + i.toString() + i.toString()});
}
jt.setModel(mtm);
ScrollPane sp = new ScrollPane();
sp.add(jt);
frame.add(sp);
frame.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
public static class MyReversedTableModel extends DefaultTableModel
{
public void reverse()
{
Collections.reverse(getDataVector());
}
#Override
public void addRow(Object[] rowData) {
reverse();
super.addRow(rowData);
reverse();
}
}
}
You can also call reverse() outside of the model to save some cpu time.

How to change column width of a table

For the following code, I am not able to set the column size to a custom size. Why is it so?Also the first column is not being displayed.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
public class Trial extends JFrame{
public void create(){
JPanel jp = new JPanel();
String[] string = {" ", "A"};
Object[][] data = {{"A", "0"},{"B", "3"},{"C","5"},{"D","-"}};
JTable table = new JTable(data, string);
jp.setLayout(new GridLayout(2,0));
jp.add(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumn column = null;
for (int i = 0; i < 2; i++) {
column = table.getColumnModel().getColumn(i);
column.setPreferredWidth(20); //custom size
}
setLayout(new BorderLayout());
add(jp);
}
public static void main(String [] a){
Trial trial = new Trial();
trial.setSize(300,300);
trial.setVisible(true);
trial.setDefaultCloseOperation(Trial.EXIT_ON_CLOSE);
trial.create();
}
}
You've got a couple of issues here. First and foremost, Always initialize your JFrame from the Swing EDT as such:
public static void main(String[] a) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Trial trial = new Trial();
trial.setSize(300, 300);
trial.setDefaultCloseOperation(Trial.EXIT_ON_CLOSE);
trial.create();
}
});
}
Failure to do so will lead to subtle errors. Second: JTables like to exist within JScrollPanes. That's why you don't see the column headers:
JScrollPane pane = new JScrollPane();
pane.setViewportView(table);
jp.add(pane);
With the above done, I see your tiny little columns, each 20 pixels wide.
When autoresize mode is set to off the column widths will not be adjusted at all when the table is layed out. From JTable's doLayout() documentation:
AUTO_RESIZE_OFF: Don't automatically
adjust the column's widths at all. Use
a horizontal scrollbar to accomodate
the columns when their sum exceeds the
width of the Viewport. If the JTable
is not enclosed in a JScrollPane this
may leave parts of the table
invisible.
Try adding the JTable to a JScrollPane and then adding that to the panel.

Categories

Resources