Related
I am writing an application which uses a JScrollPane. In this JScrollPane I want to automatically display search results, This means, that I have to dynamically add and remove the results within the JScrollPane. The results are realised as JTextArea, which are embeded within a GridBagLayout.
When there is a high number of search results, the JScrollPane automatically scrolls to the bottom (It should be at the top). I have solved it with a solution I found here. The problem hereby is, that you can see, how it scrolls back to the top. Is it possible to remove this behaviour?
The following things I found out:
I have to remove the previous search results to display the new ones. If I don't remove the previous ones, it displays correctly.
It neither solves the prblem wgeb I update the JScrollPane every tune after adding arow nor when updating only after adding all rows.
The best would be to just disable autoscroll. I have created an executable example to demonstrate this behavior. When clicking the button "Add Row", 500 rows are added. When clicking it several times, it becomes very clear.
Thank you very much for your help!
import java.awt.GridBagConstraints;
import javax.swing.JTextArea;
public class ScrollPaneTest extends javax.swing.JFrame {
private javax.swing.JButton jButton1;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
/**
* Creates new form ScrollPaneTest
*/
public ScrollPaneTest() {
initComponents();
}
/**
* Adds a new row.
* #param index The index of the new row.
*/
private void addRow(int index) {
JTextArea row = new JTextArea("Area " + index);
row.setEditable(false);
row.setBorder(null);
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = index;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
jPanel2.add(row, gridBagConstraints);
}
/**
* Initializes the components.
*/
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane1.setPreferredSize(new java.awt.Dimension(400, 400));
jScrollPane1.setViewportView(jPanel1);
jPanel1.setLayout(new java.awt.BorderLayout());
jPanel2.setLayout(new java.awt.GridBagLayout());
jPanel1.add(jPanel2, java.awt.BorderLayout.NORTH);
jScrollPane1.setViewportView(jPanel1);
jButton1.setText("Create Rows");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(148, 148, 148)
.addComponent(jButton1)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 245, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButton1)
.addGap(0, 21, Short.MAX_VALUE))
);
pack();
}
/**
* Creates 500 new rows.
* #param evt
*/
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
jPanel2.removeAll();
for(int i = 0; i < 1000; i++) {
addRow(i);
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jScrollPane1.getVerticalScrollBar().setValue(0);
}
});
jPanel2.validate();
jPanel2.repaint();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ScrollPaneTest().setVisible(true);
}
});
}
}
UPDATE 1
I removed the lambda expressions. Hopefully it should be now compileable also with < Java 8.
UPDATE 2
The problem with the disturbing scrolling behavior has been solved by replacing
jPanel2.validate();
jPanel2.repaint();
with
jScrollPane1.validate();
jScrollPane1.repaint();
Nevertheless, both answers to this question can be very helpful in some other cases and should be given attention.
One way to achieve this is to have a custom JViewPort for your scrollpane. This custom viewport overrides setViewPosition and uses a flag to prevent the scroll, or not.
Here is an example of such code, before changing the content of the textarea, we "lock" the viewport to prevent scrolling, and we unlock it later:
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TestNoScrolling {
private int lineCount = 0;
private LockableViewPort viewport;
private JTextArea ta;
private final class LockableViewPort extends JViewport {
private boolean locked = false;
#Override
public void setViewPosition(Point p) {
if (locked) {
return;
}
super.setViewPosition(p);
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
}
protected void initUI() {
JFrame frame = new JFrame("test");
ta = new JTextArea(5, 30);
JScrollPane scrollpane = new JScrollPane();
viewport = new LockableViewPort();
viewport.setView(ta);
scrollpane.setViewport(viewport);
frame.add(scrollpane);
frame.pack();
frame.setVisible(true);
Timer t = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
viewport.setLocked(true);
ta.append("Some new line " + lineCount++ + "\n");
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
viewport.setLocked(false);
}
});
}
});
t.setRepeats(true);
t.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestNoScrolling().initUI();
}
});
}
}
You could simply set the Caret position to the start position (0), for example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ScrollNoMore {
public static void main(String[] args) {
new ScrollNoMore ();
}
public ScrollNoMore () {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea ta;
private JScrollPane sp;
private Random rnd = new Random();
private boolean initalised = false;
public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(20, 40);
sp = new JScrollPane(ta);
add(sp);
Timer timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long value = rnd.nextLong();
ta.append(String.valueOf(value) + "\n");
if (!initalised) {
ta.setCaretPosition(0);
initalised = true;
}
}
});
timer.start();
}
}
}
This will only set it the first time the Timer runs, this means that if you move the Caret or scroll position for some reason, it won't "flick" back. You could set up a series of states where by if the user moved the current view, it didn't effect the scrolling, but could be reset as required.
i am creating a desktop application which has a window containing two frames, one inside another, internal frame containing JMENUBAR, so my question is how to get focus on first jmenu when this window opens, and it looks like:
below is the code for help
import java.awt.event.KeyEvent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Frame1 extends javax.swing.JFrame {
public static final String DATE_FORMAT_NOW = "dd-MMM-YYYY";
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
public Frame1() {
initComponents();
String dt = sdf.format(cal.getTime());
cur_date.setText(dt);
setBindings();
}
private void setBindings(){
sales_invoicing.setMnemonic(KeyEvent.VK_S);
}
private void formFocusGained(java.awt.event.FocusEvent evt) {
try {
// TODO add your handling code here:
jInternalFrame1.setSelected(true);
jInternalFrame1.requestFocus(true);
} catch (PropertyVetoException ex) {
Logger.getLogger(Carlsberg.class.getName()).log(Level.SEVERE, null, ex);
}
}
#SuppressWarnings("unchecked")
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
cur_date = new javax.swing.JLabel();
jInternalFrame1 = new javax.swing.JInternalFrame();
jPanel2 = new javax.swing.JPanel();
jLabel5 = new javax.swing.JLabel();
jMenuBar1 = new javax.swing.JMenuBar();
sales_invoicing = new javax.swing.JMenu();
jMenu6 = new javax.swing.JMenu();
jMenuItem1 = new javax.swing.JMenuItem();
jMenu8 = new javax.swing.JMenu();
jMenuItem2 = new javax.swing.JMenuItem();
jMenuItem7 = new javax.swing.JMenuItem();
jMenuItem3 = new javax.swing.JMenuItem();
jMenuItem4 = new javax.swing.JMenuItem();
jMenuItem5 = new javax.swing.JMenuItem();
jMenuItem6 = new javax.swing.JMenuItem();
jMenu10 = new javax.swing.JMenu();
jMenu11 = new javax.swing.JMenu();
jMenu7 = new javax.swing.JMenu();
jMenu2 = new javax.swing.JMenu();
jMenu4 = new javax.swing.JMenu();
jMenu3 = new javax.swing.JMenu();
jMenu5 = new javax.swing.JMenu();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setResizable(false);
addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
formFocusGained(evt);
}
});
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION));
jLabel1.setText("");
jLabel2.setText("");
jLabel3.setText("");
cur_date.setText("Nov 16,2013");
jInternalFrame1.setVisible(true);
jPanel2.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
jLabel5.setText(" Main Menu");
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGap(118, 118, 118)
.addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(128, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(jLabel5)
.addContainerGap(24, Short.MAX_VALUE))
);
sales_invoicing.setText("Sales Invoicing");
sales_invoicing.setFocusCycleRoot(true);
sales_invoicing.setFocusPainted(true);
sales_invoicing.setFocusTraversalPolicyProvider(true);
jMenu6.setText("");
jMenuItem1.setText("");
jMenu6.add(jMenuItem1);
jMenu8.setText("");
jMenuItem2.setText("");
jMenu8.add(jMenuItem2);
jMenuItem7.setText("");
jMenu8.add(jMenuItem7);
jMenuItem3.setText("");
jMenu8.add(jMenuItem3);
jMenu6.add(jMenu8);
jMenuItem4.setText("");
jMenu6.add(jMenuItem4);
jMenuItem5.setText("");
jMenu6.add(jMenuItem5);
jMenuItem6.setText("");
jMenu6.add(jMenuItem6);
jMenu10.setText("");
jMenu6.add(jMenu10);
jMenu11.setText("");
jMenu6.add(jMenu11);
sales_invoicing.add(jMenu6);
jMenu7.setText("");
sales_invoicing.add(jMenu7);
jMenuBar1.add(sales_invoicing);
jMenu2.setText("Stock Transfer");
jMenuBar1.add(jMenu2);
jMenu4.setText("Accounts");
jMenuBar1.add(jMenu4);
jMenu3.setText("Inventory");
jMenuBar1.add(jMenu3);
jMenu5.setText("Exit");
jMenuBar1.add(jMenu5);
jInternalFrame1.setJMenuBar(jMenuBar1);
javax.swing.GroupLayout jInternalFrame1Layout = new javax.swing.GroupLayout(jInternalFrame1.getContentPane());
jInternalFrame1.getContentPane().setLayout(jInternalFrame1Layout);
jInternalFrame1Layout.setHorizontalGroup(
jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jInternalFrame1Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(170, 170, 170))
);
jInternalFrame1Layout.setVerticalGroup(
jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame1Layout.createSequentialGroup()
.addGap(109, 109, 109)
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(136, Short.MAX_VALUE))
);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(72, 72, 72)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(12, 12, 12)
.addComponent(jLabel3))
.addComponent(jLabel2))
.addGap(185, 190, Short.MAX_VALUE)
.addComponent(cur_date)
.addContainerGap())
.addComponent(jInternalFrame1, javax.swing.GroupLayout.Alignment.TRAILING)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel2)
.addGap(4, 4, 4)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jLabel3)
.addComponent(cur_date))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jInternalFrame1))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Frame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Frame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Frame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Frame1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Frame1().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel cur_date;
private javax.swing.JInternalFrame jInternalFrame1;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel5;
private javax.swing.JMenu jMenu10;
private javax.swing.JMenu jMenu11;
private javax.swing.JMenu jMenu2;
private javax.swing.JMenu jMenu3;
private javax.swing.JMenu jMenu4;
private javax.swing.JMenu jMenu5;
private javax.swing.JMenu jMenu6;
private javax.swing.JMenu jMenu7;
private javax.swing.JMenu jMenu8;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JMenuItem jMenuItem1;
private javax.swing.JMenuItem jMenuItem2;
private javax.swing.JMenuItem jMenuItem3;
private javax.swing.JMenuItem jMenuItem4;
private javax.swing.JMenuItem jMenuItem5;
private javax.swing.JMenuItem jMenuItem6;
private javax.swing.JMenuItem jMenuItem7;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JMenu sales_invoicing;
// End of variables declaration//GEN-END:variables
}
please help me to write the code
i want focus on sales_invoicing so that i can operate it by keyboard
Maybe you want to add a mnemonic to the menu and accelorators to the menu items. Something like this
private void setBindings(){
sales_invoicing.setMnemonic(KeyEvent.VK_S);
jMenuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.CTRL_DOWN_MASK));
jMenuItem2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.CTRL_DOWN_MASK));
jMenuItem3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.CTRL_DOWN_MASK));
jMenuItem4.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4, InputEvent.CTRL_DOWN_MASK));
}
The sales_invoiceing has a Mnemonic of s, so to open that menu, you Alt + S
For the MenuItems they have accelerators using the ctrl key plus a number corresponding the to the menu item.
Here's an example
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class SalesMenu extends JFrame {
JMenuBar menubar;
JMenu sales_invoicing;
JMenuItem jMenuItem1;
JMenuItem jMenuItem2;
JMenuItem jMenuItem3;
JMenuItem jMenuItem4;
public SalesMenu() {
menubar = new JMenuBar();
sales_invoicing = new JMenu("Sales Invoice");
jMenuItem1 = new JMenuItem("Item 1");
jMenuItem2 = new JMenuItem("Item 2");
jMenuItem3 = new JMenuItem("Item 3");
jMenuItem4 = new JMenuItem("Item 4");
sales_invoicing.add(jMenuItem1);
sales_invoicing.add(jMenuItem2);
sales_invoicing.add(jMenuItem3);
sales_invoicing.add(jMenuItem4);
setBindings();
menubar.add(sales_invoicing);
setJMenuBar(menubar);
}
private void setBindings(){
sales_invoicing.setMnemonic(KeyEvent.VK_S);
jMenuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.CTRL_DOWN_MASK));
jMenuItem2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.CTRL_DOWN_MASK));
jMenuItem3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.CTRL_DOWN_MASK));
jMenuItem4.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4, InputEvent.CTRL_DOWN_MASK));
}
public static void createAndShowGui() {
JFrame frame = new SalesMenu();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(300, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You can see the undeline under the mnemonic for the menu and you can see the accelerators for the menu items
Edit : run this example. It uses an internal frame. Once the program opens, the focus in on the internal frame, so you can access the key binding immediately. There's two class files. A test class, and the Internal frame class
InternalFrameMenuTest.java
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.SwingUtilities;
public class InternalFrameMenuTest extends JFrame {
public InternalFrameMenuTest() {
JDesktopPane desktop = new JDesktopPane();
InternalFrameMenu iframe = new InternalFrameMenu();
desktop.add(iframe);
iframe.setVisible(true);
iframe.setFocusable(true);
try {
iframe.setSelected(true);
} catch (Exception ex) {
}
add(desktop);
}
public static void createAndShowGui() {
JFrame frame = new InternalFrameMenuTest();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setSize(350, 350);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
InternalFrameMenu.java
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
public class InternalFrameMenu extends JInternalFrame {
JMenuBar menubar;
JMenu sales_invoicing;
JMenuItem jMenuItem1;
JMenuItem jMenuItem2;
JMenuItem jMenuItem3;
JMenuItem jMenuItem4;
JLabel label = new JLabel(" ");
public InternalFrameMenu() {
super("Internal Frame", true, true, true, true);
menubar = new JMenuBar();
sales_invoicing = new JMenu("Sales Invoice");
jMenuItem1 = new JMenuItem("Item 1");
jMenuItem2 = new JMenuItem("Item 2");
jMenuItem3 = new JMenuItem("Item 3");
jMenuItem4 = new JMenuItem("Item 4");
setBindings();
sales_invoicing.add(jMenuItem1);
sales_invoicing.add(jMenuItem2);
sales_invoicing.add(jMenuItem3);
sales_invoicing.add(jMenuItem4);
menubar.add(sales_invoicing);
setJMenuBar(menubar);
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
add(label);
setSize(250, 250);
setLocation(20, 20);
}
private void setBindings() {
sales_invoicing.setMnemonic(KeyEvent.VK_S);
jMenuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.CTRL_DOWN_MASK));
jMenuItem2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.CTRL_DOWN_MASK));
jMenuItem3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.CTRL_DOWN_MASK));
jMenuItem4.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4, InputEvent.CTRL_DOWN_MASK));
}
}
hey guys i got the answer to get focus on internal frame, see code below
private void formFocusGained(java.awt.event.FocusEvent evt) {
try {
// TODO add your handling code here:
jInternalFrame1.setSelected(true);
jInternalFrame1.requestFocus(true);
} catch (PropertyVetoException ex) {
Logger.getLogger(Carlsberg.class.getName()).log(Level.SEVERE, null, ex);
}
}
I am creating 4 threads and each thread is associated with a UI.
The UI performs a long running task, for that I have used a SwingWorker.
But the problem that arises is instead of running as a multithreaded app, it is running in queue.
Interesting to note that when I remove the SwingWorker it behaves and runs as multithreaded.
My code is as:
NewClass
package thread;
public class NewClass
{
public static void main(String[] args) throws Exception
{
for(int i=0; i<4 ; i++)
{
new ThreadFront().startsThread();
Thread.sleep(2000);
}
}
}
class ThreadFront implements Runnable
{
private Thread t;
public ThreadFront()
{
t = new Thread(this, "");
}
public void startsThread()
{
t.start();
}
#Override
public void run()
{
try
{
UI ui = new UI();
ui.startThread();
}
catch(Exception ae)
{
ae.printStackTrace();
}
}
}
UI class
package thread;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class UI extends javax.swing.JFrame
{
public UI()
{
initComponents();
setVisible(true);
}
public void startThread() throws Exception
{
new SwingWorker<Integer, Integer>()
{
#Override
protected Integer doInBackground() throws Exception
{
for(int i=0; i<10;i++)
{
jTextArea1.append(""+i);
Thread.sleep(3000);
}
return 0;
}
#Override
protected void process(List<Integer> chunks)
{
for(Integer message : chunks)
{
jProgressBar1.setValue(message);
jProgressBar1.repaint();
}
}
#Override
protected void done()
{
try
{
get();
}
catch(final Exception ex)
{
ex.printStackTrace();
}
}
}.execute();
}
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
jPanel3 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
jLabel2 = new javax.swing.JLabel();
jobid_field = new javax.swing.JLabel();
jProgressBar1 = new javax.swing.JProgressBar();
work_field = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
session_field = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setLocationByPlatform(true);
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
formWindowClosing(evt);
}
});
jPanel1.setLayout(new java.awt.BorderLayout());
jPanel2.setBackground(new java.awt.Color(204, 204, 204));
jPanel2.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(255, 255, 255)));
jPanel2.setForeground(new java.awt.Color(204, 204, 204));
jLabel1.setFont(new java.awt.Font("Century Gothic", 1, 14)); // NOI18N
jLabel1.setText("iZoneX Math Process");
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 304, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(86, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
jPanel1.add(jPanel2, java.awt.BorderLayout.NORTH);
jPanel3.setBackground(new java.awt.Color(204, 204, 204));
jPanel3.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(255, 255, 255)));
jTextArea1.setEditable(false);
jTextArea1.setBackground(new java.awt.Color(255, 255, 204));
jTextArea1.setColumns(20);
jTextArea1.setFont(new java.awt.Font("Century Gothic", 1, 12)); // NOI18N
jTextArea1.setForeground(new java.awt.Color(255, 0, 0));
jTextArea1.setLineWrap(true);
jTextArea1.setRows(5);
jTextArea1.setWrapStyleWord(true);
jScrollPane1.setViewportView(jTextArea1);
jLabel2.setText("Job ID. :");
jLabel4.setText("Processing: ");
jLabel3.setText("Session ID: ");
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel3Layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jobid_field, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(33, 33, 33)
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(session_field, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(jProgressBar1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel3Layout.createSequentialGroup()
.addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(work_field, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jobid_field, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel3)
.addComponent(session_field, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 148, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(work_field, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
jPanel1.add(jPanel3, java.awt.BorderLayout.CENTER);
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
pack();
}// </editor-fold>
private void formWindowClosing(java.awt.event.WindowEvent evt) {
}
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JProgressBar jProgressBar1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JLabel jobid_field;
private javax.swing.JLabel session_field;
private javax.swing.JLabel work_field;
// End of variables declaration
}
What would be the alternative to worker Threads in Swing in that case?
Um, no, this is not how multithreading works in Swing.
There is a single UI thread (known as the Event Dispatching Thread), all updates and interactions with the UI are expected to be done from within the context of the EDT, so doing things like...
#Override
public void run()
{
try
{
UI ui = new UI();
ui.startThread();
}
catch(Exception ae)
{
ae.printStackTrace();
}
}
And...
#Override
protected Integer doInBackground() throws Exception
{
for(int i=0; i<10;i++)
{
jTextArea1.append(""+i);
Thread.sleep(3000);
}
return 0;
}
Are actually breaking this rule.
Instead, each UI should have its own SwingWorker (as it does now), but should be created from within the context of the EDT.
Each SwingWorker should be calling publish in order to push the results of the doInBackground method back to the EDT.
SwingWorker has its own progress support via the PropertyChange support
For example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MultiThreadedUI {
public static void main(String[] args) {
new MultiThreadedUI();
}
public MultiThreadedUI() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
final List<TestPane> panes = new ArrayList<>(5);
for (int index = 0; index < 5; index++) {
panes.add(new TestPane(Integer.toString(index)));
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 1));
for (TestPane pane : panes) {
frame.add(pane);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
for (TestPane pane : panes) {
pane.makeItSo();
}
}
});
}
});
}
public class TestPane extends JPanel {
private JTextArea textArea;
private JProgressBar pb;
private String name;
public TestPane(String name) {
this.name = name;
textArea = new JTextArea(10, 5);
pb = new JProgressBar();
setLayout(new BorderLayout());
add(new JScrollPane(textArea));
add(pb, BorderLayout.SOUTH);
}
public void makeItSo() {
BackgroundWorker worker = new BackgroundWorker();
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
pb.setValue((Integer)evt.getNewValue());
}
}
});
worker.execute();
}
protected class BackgroundWorker extends SwingWorker<Integer, Integer> {
#Override
protected void process(List<Integer> chunks) {
for (Integer value : chunks) {
textArea.append(name + ": " + value + "\n");
}
}
#Override
protected Integer doInBackground() throws Exception {
int delay = (int)(Math.random() * 3000);
for (int i = 0; i < 10; i++) {
publish(i);
setProgress((int) (Math.round(((double) i / (double) 9) * 100)));
Thread.sleep(delay);
}
return 0;
}
}
}
}
I have downloaded a snake game project in java and try to modify it. Initially the project contains three java files
i.e "Engine.java" , "Snake.java", "GameBoard.java". And Engine.java have the main() method, and when i run this Engine.java class game starts running.
To improve the user iteractivity towards the project i have created two JFrames :"PlayGame.java", Rules.java
Now this project having five java classes -
Engine.java(containing main() method)
Snake.java
GameBoard.java
PlayGame.java(is a JFrame)
Rules.java(is a JFrame)
PlayGame.java have three buttons
Play - i want when play button get clicked snake game start/run.
Rules - when clicked Rules.java Jframe should be opened
Exit - exits the application
Now what i want is at first "PlayGame.java" JFrame should appear(and this is appearing as the main output of the game project) and throw this game should start i.e when i click play button from PlayGame JFrame game should start
The problem i am facing is when i click play button then gamescreen appears on the window but snake is not moving.
Here is the code that i have included in actionPerformed() method of Play button
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
JFrame frame = new JFrame("SnakeGame");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setResizable(true);
Canvas canvas = new Canvas();
canvas.setBackground(Color.black);
canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE * GameBoard.TILE_SIZE, GameBoard.MAP_SIZE * GameBoard.TILE_SIZE));
frame.getContentPane().add(canvas);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
new Engine(canvas).startGame();
}
and also i am showing code of startGame() method which is in Engine.java class
public void startGame() {
canvas.createBufferStrategy(2);
Graphics2D g = (Graphics2D)canvas.getBufferStrategy().getDrawGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
long start = 0L;
long sleepDuration = 0L;
while(true) {
start = System.currentTimeMillis();
update();
render(g);
canvas.getBufferStrategy().show();
g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
sleepDuration = (1500L / UPDATES_PER_SECOND) - (System.currentTimeMillis() - start);
if(sleepDuration > 0) {
try {
Thread.sleep(sleepDuration);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Here also i am attaching the Engine.java class and PlayGame.java in my question for better understandig of problem
Engine.java
package org.psnbtech;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import org.psnbtech.GameBoard.TileType;
import org.psnbtech.Snake.Direction;
public class Engine extends KeyAdapter {
private static final int UPDATES_PER_SECOND = 15;
private static final Font FONT_SMALL = new Font("Arial", Font.BOLD, 20);
private static final Font FONT_LARGE = new Font("Arial", Font.BOLD, 40);
public Canvas canvas;
public GameBoard board;
public Snake snake;
public int score;
public boolean gameOver;
public Engine(Canvas canvas) {
this.canvas = canvas;
this.board = new GameBoard();
this.snake = new Snake(board);
resetGame();
canvas.addKeyListener(this);
//new Engine(canvas).startGame();
}
public void startGame() {
canvas.createBufferStrategy(2);
Graphics2D g = (Graphics2D)canvas.getBufferStrategy().getDrawGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
long start = 0L;
long sleepDuration = 0L;
while(true) {
start = System.currentTimeMillis();
update();
render(g);
canvas.getBufferStrategy().show();
g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
sleepDuration = (1500L / UPDATES_PER_SECOND) - (System.currentTimeMillis() - start);
if(sleepDuration > 0) {
try {
Thread.sleep(sleepDuration);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
public void update() {
if(gameOver || !canvas.isFocusOwner()) {
return;
}
TileType snakeTile = snake.updateSnake();
if(snakeTile == null || snakeTile.equals(TileType.SNAKE)) {
gameOver = true;
} else if(snakeTile.equals(TileType.FRUIT)) {
score += 10;
spawnFruit();
}
}
public void render(Graphics2D g) {
board.draw(g);
g.setColor(Color.WHITE);
if(gameOver) {
g.setFont(FONT_LARGE);
String message = new String("Your Score: " + score);
g.drawString(message, canvas.getWidth() / 2 - (g.getFontMetrics().stringWidth(message) / 2), 250);
g.setFont(FONT_SMALL);
message = new String("Press Enter to Restart the Game");
g.drawString(message, canvas.getWidth() / 2 - (g.getFontMetrics().stringWidth(message) / 2), 350);
} else {
g.setFont(FONT_SMALL);
g.drawString("Score:" + score, 10, 20);
}
}
public void resetGame() {
board.resetBoard();
snake.resetSnake();
score = 0;
gameOver = false;
spawnFruit();
}
public void spawnFruit() {
int random = (int)(Math.random() * ((GameBoard.MAP_SIZE * GameBoard.MAP_SIZE) - snake.getSnakeLength())); // if '*' replace by '/' then only one fruit is there for snake
int emptyFound = 0;
int index = 0;
while(emptyFound < random) {
index++;
if(board.getTile(index % GameBoard.MAP_SIZE, index / GameBoard.MAP_SIZE).equals(TileType.EMPTY)) { // if '/' replaced by '*' then nothing displays on the board
emptyFound++;
}
}
board.setTile(index % GameBoard.MAP_SIZE, index / GameBoard.MAP_SIZE, TileType.FRUIT); // it also show nothing when replacing '/' by '/'
}
#Override
public void keyPressed(KeyEvent e) {
if((e.getKeyCode() == KeyEvent.VK_UP)||(e.getKeyCode() == KeyEvent.VK_W)) {
snake.setDirection(Direction.UP);
}
if((e.getKeyCode() == KeyEvent.VK_DOWN)||(e.getKeyCode() == KeyEvent.VK_S)) {
snake.setDirection(Direction.DOWN);
}
if((e.getKeyCode() == KeyEvent.VK_LEFT)||(e.getKeyCode() == KeyEvent.VK_A)) {
snake.setDirection(Direction.LEFT);
}
if((e.getKeyCode() == KeyEvent.VK_RIGHT)||(e.getKeyCode() == KeyEvent.VK_D)) {
snake.setDirection(Direction.RIGHT);
}
if(e.getKeyCode() == KeyEvent.VK_ENTER && gameOver) {
resetGame();
}
}
public static void main(String[] args) {
new PlayGame().setVisible(true);
/**JFrame frame = new JFrame("SnakeGame");
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setResizable(false);
Canvas canvas = new Canvas();
canvas.setBackground(Color.black);
canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE * GameBoard.TILE_SIZE, GameBoard.MAP_SIZE * GameBoard.TILE_SIZE));
frame.getContentPane().add(canvas);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
new Engine(canvas).startGame();*/
}
}
PlayGame.java
package org.psnbtech;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class PlayGame extends javax.swing.JFrame {
public PlayGame() {
initComponents();
}
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jButton2 = new javax.swing.JButton();
jButton3 = new javax.swing.JButton();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/psnbtech/GUID-4ED364DF-2D44-40F5-9F05-31D451F15EF1-low.png"))); // NOI18N
jButton2.setText("Rules");
jButton2.setMaximumSize(new java.awt.Dimension(89, 39));
jButton2.setMinimumSize(new java.awt.Dimension(89, 39));
jButton2.setPreferredSize(new java.awt.Dimension(89, 41));
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
jButton3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/psnbtech/exit (1).png"))); // NOI18N
jButton3.setText("Exit");
jButton3.setPreferredSize(new java.awt.Dimension(89, 41));
jButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton3ActionPerformed(evt);
}
});
jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/psnbtech/play.png"))); // NOI18N
jButton1.setText("Play");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap(277, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 111, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(27, 27, 27))))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGap(40, 40, 40)
.addComponent(jButton1)
.addGap(35, 35, 35)
.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(27, 27, 27)
.addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(75, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
this.dispose();
new Rules().setVisible(true);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
JFrame frame = new JFrame("SnakeGame");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setResizable(true);
Canvas canvas = new Canvas();
canvas.setBackground(Color.black);
canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE * GameBoard.TILE_SIZE, GameBoard.MAP_SIZE * GameBoard.TILE_SIZE));
//canvas.addKeyListener((KeyListener) this);
frame.getContentPane().add(canvas);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
new Engine(canvas).startGame();
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JPanel jPanel1;
// End of variables declaration
}
Taht happens because you call
new PlayGame().setVisible(true);
and
frame.setVisible(true);
Show just the first frame and on button click the second.
The recommended approach is to use just one frame always but multiple panels 1. where game is rendered and 2. options pane. Swap them e.g. by using CardLayout.
Also don't use Canvas use JPanel instead overriding paintComponent() method.
Try the follwing:
JFrameAdd ja = new JFrameAdd();
ja.setVisible(true);
ja.setLocationRelativeTo(null);
Hope it will help!
How to make a text field visible on itemStatechanged event of a check box in Swing?
I am trying to create a frame with a check box and a text field. I want the text field to be displayed only when the check box is selected. So when I initialize the components, I have set the textfield.setvisible to false and for the check box added a addItemListener and call the itemStateChanged event and there is the check box is selected, I set the setVisible method to true.
My SSCCE looks like:
package ui;
public class Evaluator extends javax.swing.JFrame {
public Evaluator() {
initComponents();
}
private void initComponents() {
jCheckBox1 = new javax.swing.JCheckBox();
jTextField1 = new javax.swing.JTextField();
jTextField1.setVisible(false);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new java.awt.Dimension(800, 800));
jCheckBox1.setFont(new java.awt.Font("Tahoma", 0, 14));
jCheckBox1.setText("Properties");
jCheckBox1.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCheckBox1ItemStateChanged(evt);
}
});
jTextField1.setFont(new java.awt.Font("Tahoma", 0, 14));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jCheckBox1)
.addGap(41, 41, 41)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(155, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(229, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jCheckBox1)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(34, 34, 34))
);
pack();
}
private void jCheckBox1ItemStateChanged(java.awt.event.ItemEvent evt) {
// TODO add your handling code here:
if(evt.getStateChange()== java.awt.event.ItemEvent.SELECTED){
jTextField1.setVisible(true);
}
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Evaluator.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Evaluator.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Evaluator.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Evaluator.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Evaluator().setVisible(true);
}
});
}
private javax.swing.JCheckBox jCheckBox1;
private javax.swing.JTextField jTextField1;
}
Basically, you need to invalidate the frame (or parent container) to force it be re-layout
private void jCheckBox2ItemStateChanged(java.awt.event.ItemEvent evt) {
jTextField1.setVisible(jCheckBox2.isSelected());
invalidate();
validate();
}
Updated
I'd also suggest that you avoid adding your entire UI onto a top level container, instead use a JPanel as you base component and build you UI's around them. When you're ready, simply add the base panel to what ever top level container you need.
For many components in one space, use a CardLayout as see in this short example.
Here is a more specific example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class CardLayoutDemo {
public static void main(String[] args) {
Runnable r = new Runnable () {
public void run() {
final JCheckBox show = new JCheckBox("Have Text", false);
JPanel ui = new JPanel(new
FlowLayout(FlowLayout.CENTER, 5, 5));
ui.add( show );
final CardLayout cl = new CardLayout();
final JPanel cards = new JPanel(cl);
ui.add(cards);
cards.add(new JPanel(), "notext");
cards.add(new JTextField(8), "text");
ItemListener al = new ItemListener(){
public void itemStateChanged(ItemEvent ie) {
if (show.isSelected()) {
cl.show(cards, "text");
} else {
cl.show(cards, "notext");
}
}
};
show.addItemListener(al);
JOptionPane.showMessageDialog(null, ui);
}
};
SwingUtilities.invokeLater(r);
}
}
great lesson, how the LayoutManager works, only GridLayout can do that without any issue, but this is its property
last JComponent in the row or column (part of then is about) can't be invisible, then container is shrinked
easiest work_around is to display container, then to call setVisible(false) wrapped into invokeLater
... ....
import java.awt.event.ItemEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Evaluator {
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
private JCheckBox checkBox = new JCheckBox();
private JTextField textField = new JTextField(10);
public Evaluator() {
checkBox.setText("Properties");
checkBox.addItemListener(new java.awt.event.ItemListener() {
#Override
public void itemStateChanged(java.awt.event.ItemEvent evt) {
if (evt.getStateChange() == ItemEvent.SELECTED) {
textField.setVisible(true);
} else {
textField.setVisible(false);
}
}
});
//panel.setLayout(new GridLayout());
//panel.setLayout(new SpringLayout());
//panel.setLayout(new BorderLayout());
//panel.setLayout(new GridBagLayout());
//panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(checkBox/*, BorderLayout.NORTH*/);
panel.add(textField/*, BorderLayout.SOUTH*/);
//panel.doLayout();
//textField.setVisible(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
textField.setVisible(false);
}
});
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Evaluator evaluator = new Evaluator();
}
});
}
}