I added JLabel on JFrame and displayed frame on YES button click of JOptionPane, it displays frame but didn't display label text.
int yes = JOptionPane.showConfirmDialog(null,"Do you want to reactivate previous
schedule(s)","Reactivate Schedule",JOptionPane.OK_CANCEL_OPTION,
JOptionPane.INFORMATION_MESSAGE);
if(yes == JOptionPane.OK_OPTION) {
setVisible(false);
disp_wait.setVisible(true);
for(int i=0 ; i<options.taskList.size(); i++) {
dataList = Options.getInstance().getTaskList();
Task task=dataList.get(i);
boolean active = task.getActive();
if(active) {
task.setActive(true);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.getMessage();
}
}
}
}
All your code is performing some processing during an event handling. In Java this is a problem, the GUI only gets drawn once all the event handling is processed. Besides that, it would be great to see the code for your JFrame, it probably does not add the Label before calling pack()
Related
I am working on a JAVA desktop application that has two frames, users clicks a button on frame 1, response based on the selected option would be updated to the database. While the response is being updated, frame 2 should be displayed.
If I set the frame 2 to visible before the database update, frame 2 is displayed but with empty content i.e panels of frame 2 are not displayed. But once the database update is completed, the contents of the frame are shown.
button1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
frame1.setVisible(false);
frame2.setVisible(true);
Utilities.updateToDB("clicked button1");
}
});
Content of Frame 2 should be shown while the database update is taking place or before it.
For this particular case I suggest you to use:
A Swing Worker as shown in this example and the tutorial
Something along the lines:
protected String doInBackground() throws Exception {
try {
Thread.sleep(5000); //Simulates long running task (your database update)
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Updated"; //Returns the text to be set on your status JLabel once the update is done
}
#Override
protected void done() {
super.done();
try {
// Here update your GUI or do whatever you want to do when the update is done.
textfield.setText(get()); //Set to the textField the text given from the long running task
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
And on your ActionListener something like:
private ActionListener listener = (e -> {
frame2.setVisible(true); //suggested use of cardlayout and display nextCard here.
worker.execute(); //Initializes long running task
});
However I suggest you not to use multiple JFrames: The Use of Multiple JFrames: Good or Bad Practice? and use a CardLayout instead, for example
I am creating a two player Simon game, one player(client) clicks the colored squares, and the client will send the clicking sequence (as an ArrayList) to the server, and the server sends it to the other player.
Right now, the ArrayList arrives at the other client with no problem, but when I loop through the ArrayList, and inside the loop, I want the colored squares to flash. Only the last color will flash.
public void flashArray(){
for(int i=0;i<blist.size();i++){
int toFlash = blist.get(i);
setFlashed(toFlash);//for example, if toFlash==1, after repaint, the green square will be lighter, and after the timer, it will be back to normal
repaint();
Timer timer = new Timer(200, timerAction);
timer.setRepeats(false);
timer.start();
}
}
the timerAction code
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
setFlashed(F_DEFAULT);
repaint();
}
};
the flashing works when I manually click the squares, they will flash. but when I put the code into the flashArray (loop) it will not work, it will only flash the last color.
Thank you #MadProgrammer.
Using Thread.sleep(sleeptime) is worked perfectly for me.
Here is the method:
//a method to make simon flash based on the arraylist
public void flashArry(){
for(int i=0;i<blist.size();i++){
int toFlash = blist.get(i);
setFlashed(toFlash);
repaint();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(Simon.class.getName()).log(Level.SEVERE, null, ex);
}
setFlashed(F_DEFAULT);
repaint();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(Simon.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
to explain the code: loop through the integer arraylist(the integers represent the colors to flesh), set the color-> repaint (make it brighter)-> sleep->set back to default color-> repaint ->sleep ->loop to next color to flash...
I have .txt files and I read them to a JList, then I want to select a name of a file from a JComboBox, read that file, create the list and appear on the frame inside of a JScrollPane.
I have almost everything working the only problem is that I can't add the scroll pane with the list to the frame correctly and the list only appears when I press the button "envia". The way I have my code inserting the list to the scroll pane and then to the window is not correct because the scroll pane are being inserted on top of each other, but its the closest I got to wokring.
I want it to appear on the the scroll pane and on the frame correctly when I press on the combo box and not when I press "envia". I don't understand why the list only appears when I press that button.
combo2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
falarpara = combo2.getSelectedItem().toString();
try {
lista = f.getList(user, falarpara);
janela.add(lista.getlist());
JScrollPane j = new JScrollPane(lista.getlist());
janela.add(j);
janela.validate();
} catch (FileNotFoundException e4) {
// TODO Auto-generated catch block
e4.printStackTrace();
}
}
});
envia.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String a = new String(user + ":" + " " + txt.getText());
f.escreve(user, falarpara, a);
lista.add(a);
txt.setText(null);
}
});
I want to display different images in a same frame within a loop. String pathName[] contains the different paths of the images. When running this code, only last image i.e image at path pathname[last] is getting displayed on frame instead I want all images to be displayed in a continuous way (have given delay of 1sec ). Help is appreciated.
public void actionPerformed(ActionEvent event) {
int i=0;
while(i<5){
if(i>0){
Container labelParent = receiverImageLabel.getParent();
labelParent.remove(receiverImageLabel);
labelParent.validate();
labelParent.repaint();
}
try {
imageR = ImageIO.read(new File(pathName[i++])).getScaledInstance(512,512 , BufferedImage.SCALE_SMOOTH);
receivedImage = new ImageIcon(imageR);
}catch (IOException e) {
e.printStackTrace();
}
receiverImageLabel = new JLabel(receivedImage);
receiverFrame.getContentPane().add(BorderLayout.EAST,receiverImageLabel);
receiverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
receiverFrame.setSize(800,700);
receiverFrame.setVisible(true);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Your problem is a common one: you're calling Thread.sleep(...) in a Swing GUI on the event thread and are essentially thus putting the entire GUI to sleep.
Solution: Google the Swing Timer and use this in place of your while loop/Thread.sleep(...)
Also, if the images aren't too big, then consider reading them all in at once (in a background thread), putting them into ImageIcons, and then swapping out a JLabel's ImageIconsand in your Swing Timer.
For example, you could do something like:
ImageIcon[] icons = new ImageIcon[IMAGE_COUNT];
for (int i = 0; i < IMAGE_COUNT; i++) {
BufferedImage img = ImageIO.read(...); // read in the appropriate image
// ...... here manipulate the image if desired such as re-size it
icons[i] = new ImageIcon(img); // put it into an icon
}
elsewhere:
int timerDelay = 1000;
new Timer(timerDelay, new ActionListener(){
int count = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (count < IMAGE_COUNT) {
someLabel.setIcon(icons[count]);
count++;
} else {
// stop the timer
((Timer)e.getSource()).stop();
}
}
}).start();
Note: code not compiled nor tested and is posted only as a general example of steps to consider.
I am following the Oracle tutorial on how to create a custom dialog box: http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
I have two buttons: Save Object and Delete Object which when clicked should execute a certain piece of code. Unfortunately I can't seem to add any ActionListener to the JOptionPane buttons so when they're clicked nothing happens.
Can anyone help tell me how I can go about doing this? Here is the class I have for the dialog box so far:
class InputDialogBox extends JDialog implements ActionListener, PropertyChangeListener {
private String typedText = null;
private JTextField textField;
private JOptionPane optionPane;
private String btnString1 = "Save Object";
private String btnString2 = "Delete Object";
/**
* Returns null if the typed string was invalid;
* otherwise, returns the string as the user entered it.
*/
public String getValidatedText() {
return typedText;
}
/** Creates the reusable dialog. */
public InputDialogBox(Frame aFrame, int x, int y) {
super(aFrame, true);
setTitle("New Object");
textField = new JTextField(10);
//Create an array of the text and components to be displayed.
String msgString1 = "Object label:";
Object[] array = {msgString1, textField};
//Create an array specifying the number of dialog buttons
//and their text.
Object[] options = {btnString1, btnString2};
//Create the JOptionPane.
optionPane = new JOptionPane(array,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.YES_NO_OPTION,
null,
options,
options[0]);
setSize(new Dimension(300,250));
setLocation(x, y);
//Make this dialog display it.
setContentPane(optionPane);
setVisible(true);
//Handle window closing correctly.
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
/*
* Instead of directly closing the window,
* we're going to change the JOptionPane's
* value property.
*/
optionPane.setValue(new Integer(
JOptionPane.CLOSED_OPTION));
}
});
//Ensure the text field always gets the first focus.
addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent ce) {
textField.requestFocusInWindow();
}
});
//Register an event handler that puts the text into the option pane.
textField.addActionListener(this);
//Register an event handler that reacts to option pane state changes.
optionPane.addPropertyChangeListener(this);
}
/** This method handles events for the text field. */
public void actionPerformed(ActionEvent e) {
optionPane.setValue(btnString1);
System.out.println(e.getActionCommand());
}
/** This method reacts to state changes in the option pane. */
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (isVisible()
&& (e.getSource() == optionPane)
&& (JOptionPane.VALUE_PROPERTY.equals(prop) ||
JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) {
Object value = optionPane.getValue();
if (value == JOptionPane.UNINITIALIZED_VALUE) {
//ignore reset
return;
}
//Reset the JOptionPane's value.
//If you don't do this, then if the user
//presses the same button next time, no
//property change event will be fired.
optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
if (btnString1.equals(value)) {
typedText = textField.getText();
String ucText = typedText.toUpperCase();
if (ucText != null ) {
//we're done; clear and dismiss the dialog
clearAndHide();
} else {
//text was invalid
textField.selectAll();
JOptionPane.showMessageDialog(
InputDialogBox.this,
"Please enter a label",
"Try again",
JOptionPane.ERROR_MESSAGE);
typedText = null;
textField.requestFocusInWindow();
}
} else { //user closed dialog or clicked delete
// Delete the object ...
typedText = null;
clearAndHide();
}
}
}
/** This method clears the dialog and hides it. */
public void clearAndHide() {
textField.setText(null);
setVisible(false);
}
I think you're missing the point of the JOptionPane. It comes with the ability to show it's own dialog...
public class TestOptionPane02 {
public static void main(String[] args) {
new TestOptionPane02();
}
public TestOptionPane02() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JTextField textField = new JTextField(10);
String btnString1 = "Save Object";
String btnString2 = "Delete Object";
//Create an array of the text and components to be displayed.
String msgString1 = "Object label:";
Object[] array = {msgString1, textField};
//Create an array specifying the number of dialog buttons
//and their text.
Object[] options = {btnString1, btnString2};
int result = JOptionPane.showOptionDialog(null, array, "", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, "New Object", options, options[0]);
switch (result) {
case 0:
System.out.println("Save me");
break;
case 1:
System.out.println("Delete me");
break;
}
}
});
}
}
To do it manually, you're going to have to do a little more work.
Firstly, you're going to have to listen to the panel's property change events, looking for changes to the JOptionPane.VALUE_PROPERTY and ignoring any value of JOptionPane.UNINITIALIZED_VALUE...
Once you detect the change, you will need to dispose of your dialog.
The you will need extract the value that was selected via the JOptionPane#getValue method, which returns an Object. You will have to interrupt the meaning to that value yourself...
Needless to say, JOptionPane.showXxxDialog methods do all this for you...
Now if you worried about having to go through all the setup of the dialog, I'd write a utility method that either did it completely or took the required parameters...but that's just me
UPDATED
Don't know why I didn't think it sooner...
Instead of passing an array of String as the options parameter, pass an array of JButton. This way you can attach your own listeners.
options - an array of objects indicating the possible choices the user
can make; if the objects are components, they are rendered properly;
non-String objects are rendered using their toString methods; if this
parameter is null, the options are determined by the Look and Feel
For the flexibility you seem to want you should have your class extend JFrame instead of JDialog. Then declare your buttons as JButtons:
JButton saveButton = new JButton("Save"); and add an actionListnener to this button:
saveButton.addActionListener();
either you can put a class name inside the parenthesis of the saveButton, or you can simply pass it the keyword 'this' and declare a method called actionPerformed to encapsulate the code that should execute when the the button is pressed.
See this link for a JButton tutorial with more details:
http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html