Clean the window in swing - java

I have a group of jRadioButton that I created,
each button has an action listener that creates a JTable in a separate window.
I want that when I press another button, the frame will be cleaned and then the other JTable to be performed,
ButtonGroup group = new ButtonGroup();
JRadioButton[] jRadioButton = new JRadioButton[5];
for (int i = 0; i < 5; i++) {
jRadioButton[i] = new JRadioButton("machine "+i);
jRadioButton[i].setBounds(x, y, width, height);// x, y, width, height are place parameters
group.add(jRadioButton[i]);
frame.getContentPane().add(jRadioButton[i]);
frame.update(frame.getGraphics());//update the frame and add the buttons
}
let's say, I pressed machine 1 and a table popped up in a different window, now when I press machine 2 and a different table will pop up I want to clear the new window before the second table is shown.
So my question is, is it possible to clean a window and if yes how?

If the only difference is JTable you can just change the table's model with theTable.setModel(properJRadioButtonDependentModel).
If you have more controls you can either use a CardLayout swapping panels (for each JRadioButton instance you can create a panel and swap them)
OR
remove all controls using removeAll() method of container, add new controls and call
container.revalidate();
container.repaint();

the table creation
public void createMachineTable(int row) {
model = new DefaultTableModel(col, row);
table = new JTable(model) {
/**
*
*/
#Override
public boolean isCellEditable(int rows, int columns) {
if (columns == 0)
return false;//left side uneditable
else
return true;//right side editable
}
};
pane = new JScrollPane(table);// the new window of te table
getContentPane().add(pane);
setVisible(true);
setSize(500, 600);
getContentPane().setLayout(new FlowLayout());
setDefaultCloseOperation(1);
}
now, when pressing a different button, the following levels will be applied
pane.getViewport().remove( table );
createMachineTable(rowsNumer);
the table will be deleted and a new one will be created.

Related

How to drag and drop an image from label to label?

I'm new in using the DnD in java.I'm trying to drag an drop an image from a label to another. The first label is the source, the second is the destination. My trouble is that I need to drag the image from the source and recognize that i'm dropping on the correct destination; if the destination is correct the image from the source must disappear, else must come back to the source and notify it to the user using a window message or just a System.out.println(). I've tried using TransferHandler, DragSource, but I didn't get a single good result.
How to drag and drop an image from label to label?
The Drag Listener
public class DragMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
}
The Source labels that contain the images
public ShipsGUI() {
// setBorder(new EmptyBorder(10,10,10,10));
setLayout(new GridLayout(2, 5));
MouseListener listener = new DragMouseAdapter();
for (int i = 0; i < 10; i++) {
JPanel p = new JPanel(new BorderLayout(5, 0));
JLabel a = new JLabel(ship,JLabel.CENTER);
a.setName("ship");
JLabel n = new JLabel("[" + Integer.toString(i + 1) + "]");
n.setForeground(Color.BLUE);
// a.setBorderPainted(false);
// a.setBackground(Color.white);
// a.setOpaque(true);
//a.setIcon(ship,JLabel.CENTER);
a.setTransferHandler(new TransferHandler("icon"));
a.addMouseListener(listener);
p.add(a);
p.add(n, BorderLayout.LINE_START);
add(p);
}
}
The destination (it's a grid fo labels)
public NewAreaGioco(int r,int c, boolean enable){
this.setLayout(new GridLayout(r,c,1,1));
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
JLabel l= new JLabel(" ");
l.setSize(30, 30);
l.setBorder(BorderFactory.createLineBorder(Color.BLUE));
if(enable)l.setTransferHandler(new TransferHandler("icon"));
add(l);
}//fine for
}//fine for
}
Well, you can't use the default TransferHandler class. You need to make your own.
I would start by looking at the DropDemo and ListTransferHandler class found on the examples page of the Drag and Drop tutorial.
A couple of change that I think you will need to make:
export an image instead of text. I think the link provided by Sergiy above might help.
The key point is in the exportDone(...) method. Your cleanup code would set the icon of the source component to null.
You will probably need to read the tutorial to understand the concept of these two classes.

JTable#scrollRectToVisible in combination with JSplitPlane shows the wrong row

When I call JTable#scrollRectToVisible, the row I want to show is hidden underneath the header in certain situations.
The rest of this question only makes sense when using the following code. This is a very simply program which I use to illustrate the problem. It shows a UI containing a JSplitPane with in the upper part some control buttons, and the lower part contains a JTable wrapped in a JScrollPane (see screenshots at the bottom of this post).
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class DividerTest {
private final JSplitPane fSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
private final JTable fTable;
private final JScrollPane fScrollPane;
private boolean fHideTable = false;
public DividerTest() {
fTable = new JTable( createTableModel(50));
fScrollPane = new JScrollPane(fTable);
fSplitPane.setBottomComponent(fScrollPane);
fSplitPane.setTopComponent(createControlsPanel());
fSplitPane.setDividerLocation(0.5);
}
private JPanel createControlsPanel(){
JPanel result = new JPanel();
result.setLayout(new BoxLayout(result, BoxLayout.PAGE_AXIS));
final JCheckBox checkBox = new JCheckBox("Make table invisible before adjusting divider");
checkBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
fHideTable = checkBox.isSelected();
}
});
result.add(checkBox);
JButton upperRow = new JButton("Select row 10");
upperRow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectRowInTableAndScroll(10);
}
});
result.add(upperRow);
JButton lowerRow = new JButton("Select row 45");
lowerRow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectRowInTableAndScroll(45);
}
});
result.add(lowerRow);
JButton hideBottom = new JButton("Hide bottom");
hideBottom.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (fHideTable) {
fScrollPane.setVisible(false);
}
fSplitPane.setDividerLocation(1.0);
}
});
result.add(hideBottom);
JButton showBottom = new JButton("Show bottom");
showBottom.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
fScrollPane.setVisible(true);
fSplitPane.setDividerLocation(0.5);
}
});
result.add(showBottom);
return result;
}
private void selectRowInTableAndScroll( int aRowIndex ){
fTable.clearSelection();
fTable.getSelectionModel().addSelectionInterval(aRowIndex, aRowIndex);
fTable.scrollRectToVisible(fTable.getCellRect(aRowIndex, 0, true));
}
public JComponent getUI(){
return fSplitPane;
}
private TableModel createTableModel(int aNumberOfRows){
Object[][] data = new Object[aNumberOfRows][1];
for( int i = 0; i < aNumberOfRows; i++ ){
data[i] = new String[]{"Row" + i};
}
return new DefaultTableModel(data, new String[]{"Column"});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test frame");
frame.getContentPane().add(new DividerTest().getUI());
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
});
}
}
Unwanted behavior
Run the above code
Press the "Select row 10": row 10 is selected and visible
Press the "Select row 45": row 45 is selected and visible
Click the "Hide bottom" button. This will adjust the divider of the JSplitPane so that only the upper panel is visible
Click the "Select row 10" button. You see of course nothing because the table is not yet visible
Click the "Show bottom" button. The divider is adjusted, but row 10 is hidden underneath the header. I expected it to be visible without needing to scroll.
Wanted behavior
Repeat the steps from above, but make sure the "Make table invisible before adjusting divider" checkbox is selected. This will call setVisible(false) on the JScrollPane around the JTable before hiding the bottom panel.
By doing this, in the last step row 10 will be visible as the top most row, which is what I want. I just do not want to turn the scrollpane invisible: in my real application, the divider is adjusted in an animated way and as such you want to keep the table visible during the animation.
Screenshots
Unwanted: row 10 is invisible after performing the aforementioned steps
Wanted: row 10 is visible after performing the aforementioned steps
Environment
I do not think it will matter, but just in case: I am using JDK7 on a Linux system.
This seems to be caused by the way how the JViewport handles the scrollRectToVisible calls for the cases that its size is smaller than the desired rectangle. It contains a (somewhat fuzzy, but probably related) comment in the JavaDocs:
Note that this method will not scroll outside of the valid viewport; for example, if contentRect is larger than the viewport, scrolling will be confined to the viewport's bounds.
I did not go though the complete code and do all the maths and check all the cases. So a warning: The following explainations contain quite same hand-waving. But a simplified description of what this means for me in this particular case:
When the bottom part is hidden (by setting the divider location accordingly), then this height of the JScrollPane and its JViewport is 0. Now, when requesting to scrollRectToVisible with a rectangle that has a height of 20 (for one table row, as an example), then it will notice that this does not fit. Depending on the current view position of the JViewport, this may cause to viewport to be scrolled so that the bottom of this rectangle is visible.
(You can observe this: Drag the divider location manually, so that approximately half of one table row is visible. When clicking the "Select row 45" button, the upper half of the row will be visible. When clicking the "Select row 10" button, then the lower half of the row will be visible)
One pragmatic solution here that seemed to work for me was to make sure that it will always scroll so that the top of the rectangle is visible (even when the rectangle does not at all fit into the viewport!). Like this:
private void selectRowInTableAndScroll(int aRowIndex)
{
fTable.clearSelection();
fTable.getSelectionModel().addSelectionInterval(aRowIndex, aRowIndex);
Rectangle r = fTable.getCellRect(aRowIndex, 0, true);
r.height = Math.min(fScrollPane.getHeight(), r.height);
fTable.scrollRectToVisible(r);
}
But I can't promise that this will have the desired effect for you, when an animation comes into play...
Not exactly sure what the scrollRectToVisible() is doing.
You might be able to use the JViewport.setViewPosition(...) method.
Rectangle r = fTable.getCellRect(aRowIndex, 0, true);
Point p = new Point(r.x, r.y);
fScrollPane.getViewport().setViewPosition( p );
In this case the selected row will always be shown at the top of the viewport (if possible). So the viewport will always scroll unless the selected row is current at the top. Using this approach if the first row is at the top of the viewport and you select the 10th row the viewport will scroll to display the 10th row at the top.
However, this behaviour is slightly different than using the scrollRectToVisible() method. When using the scrollRectToVisible() method the viewport when only scrolled when the rectangle is not in the visible part of the viewport. Using this approach if the first row is at the top of the viewport and you select the 10th row the viewport will NOT scroll since the 10th row is already visible in the viewport.
Don't know if this change in functionality is acceptable or not.
Note if you don't want to viewport to automatically scroll when you select a row you could try something like:
JViewport viewport = fScrollPane.getViewport();
Rectangle viewRect = viewport.getViewRect();
Rectangle r = fTable.getCellRect(aRowIndex, 0, true);
Point p = new Point(r.x, r.y);
if (! viewRect.contains(p))
viewport.setViewPosition( p );

JTable inside a JPanel inside a JOptionPane won't resize as wanted

I have two JTable objects inside a JPanel with GridLayout. I put them in a JOptionPane and I show them as an OK_CANCEL popup. I also put a JScrollPane on both tables.
However, the JOptionPane's size is enormous. I have tried setting different table, scroll pane and jpanel sizes with:
table.setSize(int w, int h)
jpanel.setSize(int w, int h)
jscrollpane.setSize(int w, int h)
but none of those would result in a smaller JOptionPane (or table).
This is how it looks, I use 1366*768 as resolution. None of the mentioned above would make any difference
private void showEditItemSuppliersDialog()
{
String newItemSupplierTables [] = { "#", "Name", "" };
JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5));
/* table 1 */
allItemsEditItemSuppliersTableModel = new DefaultTableModel(null, newItemSupplierTables);
allItemsEditItemSuppliersTable = new JTable(allItemsEditItemSuppliersTableModel);
allItemsEditItemSuppliersTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane allItemsEditItemSuppliersTableScrollPane = new JScrollPane();
allItemsEditItemSuppliersTableScrollPane.setViewportView(allItemsEditItemSuppliersTable);
/* table 1 end */
/* table 2 */
allItemsEditItemSuppliersAllTableModel = new DefaultTableModel(null, newItemSupplierTables);
allItemsEditItemSuppliersAllTable = new JTable(allItemsEditItemSuppliersAllTableModel);
allItemsEditItemSuppliersAllTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane allItemsEditItemSuppliersAllTableScrollPane = new JScrollPane();
allItemsEditItemSuppliersAllTableScrollPane.setViewportView(allItemsEditItemSuppliersAllTable);
/* table 2 end*/
panel.add(allItemsEditItemSuppliersTableScrollPane);
panel.add(allItemsEditItemSuppliersAllTableScrollPane);
int option = JOptionPane.showConfirmDialog(null, panel, "Edit", JOptionPane.OK_CANCEL_OPTION);
if (option == JOptionPane.YES_OPTION)
{
System.out.println("Pressed OK");
}
}
You should set the preferred viewport size of the tables using setPreferredScrollableViewportSize(Dimension).

Fit JTable to fill the JPanel

Hi here are my codes for my table settings:
String [] column = {"MacAddress","PcName","OperatingSystem","IpAddress","Port","Status"};
model = new DefaultTableModel(0,column.length);
model.setColumnIdentifiers(column);
mainTable = new JTable(model);
mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for(int i=0;i<=column.length-1;i++){
mainTable.getColumnModel().getColumn(i).setPreferredWidth(300);
}
pane = new JScrollPane(mainTable);
pnlTabel = new JPanel();
pnlTabel.setBorder(BorderFactory.createTitledBorder(""));
pnlTabel.setPreferredSize(new Dimension(dim.width*70/100, dim.height*60/100));
pnlTabel.add(pane);
addMainPanel(pnlTabel);
Here is my addMainPanel() function:
public void addMainPanel(Component pnl){
mainPanel.add(pnl);
mainPanel.revalidate();
}
And here is my code for my mainPanel:
mainPanel = new JPanel();
mainPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
add(mainPanel,"Center");
and I'm using border layout for my frame:
setLayout(new BorderLayout(0,0));
My problem is that, even i use this set of code to set my JTable to fit but it seems to fail all the this, this code:
mainTable.setAutoResizeMode(JTa![enter image description here][1]ble.AUTO_RESIZE_OFF);
for(int i=0;i<=column.length-1;i++){
mainTable.getColumnModel().getColumn(i).setPreferredWidth(300);
}
When is use that code, my jtable does not resize but only add on a horizontal scroll bar at the bottom.
No offense meant but .. your code and consequently your question is a mess ;-) Plus you don't explain what exactly you want to achieve.
Trying to detangle, taking the nested layouts/resizing characteristics (as seen in the snippets, might not be complete):
frame // BorderLayout
mainPanel // FlowLayout
pnlTabel // FlowLayout, hard-coded prefSize
pane // scrollPane
mainTable // auto-resize-off
Aside: intentionally kept untelling names to demonstrate how mixing naming schemes tend to contribute to overall confusion :-) Doesn't really matter whether you decide for pre or postFixing some type-related marker, but if you do be consistent.
In that hierarchy, there are two levels of FlowLayout which basically will layout their children at their respective prefs and adjusting their own pref accordingly, lest the pref were hard-coded on the level of the pnlTable: however the table's pref will be changed (by changing the column prefs) it cannot bubble further up because ... hard-coding the pref leads not calculating its size (neither by layoutManager and nor uiDelegate, both never get a chance to do it)
Another issue - the more interesting one :-) - is that the JScrollPane is somewhat special in
calculating its own prefSize from its view's pref/scrollablePrefViewportSize depending on whether or not the view implements Scrollable (JTable does so, though in a crappy way)
being a validationRoot: invalidating the view (or any children) doesn't bubble further up the hierarchy
Assuming that you want the table's scrollPane to grow if the prefWidts of the columns change, there are two thingies to tweak:
implement table's getPreferredScrollableWidth to return a value calculated based on the prefWidth of the columns
revalidate a container higher up in the hierarchy
Some code to play with:
final JTable table = new JTable(50, 10) {
// properties to base a reasonable prefScrollable size
int visibleColumns = 3;
int visibleRows = 10;
// hard-coded default in super
Dimension dummySuper = new Dimension(450, 400);
#Override
public Dimension getPreferredScrollableViewportSize() {
Dimension dim = super.getPreferredScrollableViewportSize();
if (!dummySuper.equals(dim)) return dim;
dim = new Dimension();
for (int column = 0; column < Math.min(visibleColumns, getColumnCount()); column++) {
dim.width += getColumnModel().getColumn(column).getPreferredWidth();
}
dim.height = visibleRows * getRowHeight();
return dim;
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for (int i = 0; i < table.getRowCount(); i++) {
table.setValueAt("row: " + i, i, 0);
}
JComponent tablePanel = new JPanel();
tablePanel.add(new JScrollPane(table));
Action sizeColumns = new AbstractAction("size columns") {
int prefWidth = 75;
#Override
public void actionPerformed(ActionEvent e) {
int newWidth = prefWidth + 15;
for (int i = 0; i < table.getColumnCount(); i++) {
if (table.getColumnModel().getColumn(i).getPreferredWidth() == prefWidth)
table.getColumnModel().getColumn(i).setPreferredWidth(newWidth);
}
prefWidth = newWidth;
// revalidate "higher up" than the table itself
frame.revalidate();
}
};
frame.add(new JButton(sizeColumns), BorderLayout.SOUTH);
If you want a JTable to fill the available space, you should put it inside a JPanel which has a BorderLayout layout manager. Also don't forget about the JScrollPane which ensures that if the table doesn't fit into the view (e.g. too many rows), scrollbars will appear:
JFrame frame = new JFrame();
// set up frame
JTable table = new JTable();
// Set up table, add data
// Frame has a content pane with BorderLayout by default
frame.getContentPane().add( new JScrollPane( table ), BorderLayout.CENTER );
If you have other content you wish to display besides the table, you can add those to the NORTH, SOUTH, EAST, WEST parts of the content panel (which can be wrapped into other panels if more components are to be placed there).

Java JFrame refuses to refresh

I am making a monopoly game in Java and for some reason I cant seem to get this JFrame popup to refresh. When I click the button, the popup will appear, but when I close it and click it again later on it the game, it continues to show the features of the 1st JFrame. I assume that a totally new JFrame is created every time you click the button, but I cant seem to refresh the content. How do I fix this?
final static JButton tradeButton = new JButton("Click to Trade Property");
tradeButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
final JPanel tradePanelcombo = new JPanel();
for(int x = 1; x< Player.Props.size(); x++)
{
if(x != Player.CurrentPlayer)
{
ArrayList<Property> props = Player.Props.get(x);
ArrayList<String> propnames = new ArrayList<String>();
for(Property prop : props)
{
propnames.add(prop.getName());
}
String[] strings = new String[propnames.size()];
for (int y = 0; y<propnames.size(); y++)
{
strings[y] = propnames.get(y);
}
JLabel confirmLabel = new JLabel("Player :" + x);
JComboBox petList = new JComboBox(strings);
petList.setPreferredSize(new Dimension(100, 150));
tradeFrame.add(confirmLabel);
tradePanelcombo.add(petList);
}
}
tradeFrame.add(tradePanelcombo, BorderLayout.PAGE_END);
tradeFrame.setPreferredSize(new Dimension(500,500));
tradeFrame.setResizable(true);
tradeFrame.pack();
tradeFrame.setVisible(true);
}
});
It appears to me that a new frame and components are created every time.
So, if the frame doesn't update, then I guess it would be because your Properties are not updated so the data added to the components doesn't change.
Edit:
You need to create a new JFrame every time, or you need to remove all the old components from the frame before adding the new components.
When you add a component to a BorderLayout, the previous component doesn't get removed. So you actually have two components in the container. When Swing paints components it actually paints the components in the reverse order that they where added to the container (this is how Z-Ordering works).
If you remove the setResizable() method, and then resize the frame I believe you should see the new components start to show given that they should increase in size as the frame size increases.

Categories

Resources