The program mostly works correctly, but does not open any window. It should show a little dialog on the bottom right of the desktop. But to another person however, compiling the same code works without problems.We have the same Java Runtime (1.8_u40). How can I fix this?
I have put the code below:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ProgressDialog {
private JDialog dialogFrame;
private JProgressBar progressBar;
private JLabel headingLabel;
private Uploader callerUploader;
public ProgressDialog() {
dialogFrame = new JDialog();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException ex) {
System.err.println(ex.toString());
}
dialogFrame.setSize(200, 50);
dialogFrame.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.insets = new Insets(5, 5, 5, 5);
headingLabel = new JLabel();
Font f = headingLabel.getFont();
f = new Font(f.getFontName(), Font.BOLD, f.getSize());
headingLabel.setFont(f);
headingLabel.setOpaque(false);
dialogFrame.add(headingLabel, constraints);
dialogFrame.setUndecorated(true);
// Bottone
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 0;
constraints.weighty = 0;
JButton xButton = new JButton("X");
xButton.setMargin(new Insets(1, 4, 1, 4));
xButton.setFocusable(false);
dialogFrame.add(xButton, constraints);
// Progress bar
constraints.gridx = 0;
constraints.gridy = 1;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.gridwidth = 2;
progressBar = new JProgressBar();
progressBar.setMaximum(100);
progressBar.setMinimum(0);
Dimension dim = new Dimension();
dim.width = 130;
dim.height = 20;
progressBar.setMinimumSize(dim);
progressBar.setStringPainted(true);
progressBar.setBorderPainted(true);
dialogFrame.add(progressBar, constraints);
xButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialogFrame.dispose();
stoppedUploaderClose();
}
});
}
private void autoPosition() {
// Per il posizionamento in basso a destra
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
// altezza taskbar
Insets toolHeight = Toolkit.getDefaultToolkit().getScreenInsets(dialogFrame.getGraphicsConfiguration());
dialogFrame.setLocation(scrSize.width - 5 - dialogFrame.getWidth(), scrSize.height - 5 - toolHeight.bottom
- dialogFrame.getHeight());
}
public void destroy() {
new Thread() {
#Override
public void run() {
try {
Thread.sleep(500);
for (float i = 1.00f; i >= 0; i -= 0.01f) {
dialogFrame.setOpacity(i);
Thread.sleep(15);
}
dialogFrame.dispose();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
public void setUploader(Uploader callerUploader) {
this.callerUploader = callerUploader;
}
public void set(int n) {
progressBar.setValue(n);
progressBar.setString(n + "");
}
public void setMessage(String headingLabel) {
this.headingLabel.setText(headingLabel);
autoPosition();
dialogFrame.setShape(new RoundRectangle2D.Double(1, 1, 200, 50, 20, 20));
dialogFrame.setVisible(true);
}
public void setWait() {
headingLabel.setText("Waiting link...");
}
public void close() {
dialogFrame.dispose();
}
public void stoppedUploaderClose() {
try {
callerUploader.stopUpload();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're making Swing calls that change the state of the Swing components of GUI from within a background thread, and this can and will lead to unpredictable errors. Better to use a Swing Timer rather than Thread.sleep(...) since all code within the Timer's ActionListener is called on the Swing event thread.
Also, I have to wonder
Just what the Uploader class does,... Likely it creates long running code, which begs the question, is it being called appropriately within a background thread? This looks like a good spot for a SwingWorker.
How is this dialog code being called?
For more direct help, consider creating and posting an sscce or a minimal example program/mcve where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
Edit: OK, I normally don't do this, but I looked at your code in your GitHub project link, and as I suspected, Uploader does long-running code on the Swing event thread, and makes calls to this class you've posted above. I suggest that you use a SwingWorker for long-running code, that you use its setProgress(...) method to change its progress state from 0 to 100, and that you use a PropertyChangeListener to listen for changes to this state, and then set the JProgressBar's value based on this. It will take a lot of work on your part, but will be well worth it. For the details, look at: Lesson: Concurrency in Swing
I have some example SwingWorker programs that you can find here:
Cant get JProgressBar to update from SwingWorker class
MVC Progress Bar Threading
How do I make my SwingWorker example work properly?
JProgressBar without JButton and PropertyChangeListener
Understanding Java ExecutorService
Related
I'm learning about Java Swing and I have found an advanced code (in my opinion) about Swing using MVC and Observer patterns. It is very difficult for me and I try to understand it. And I have 2 questions:
What exactly does DetailListener.class? It is the first time when I use .class after an interface. I have tried to search on stackoverflow about ".class syntax" and I see it can be used after a class, but I still don't understand what it does in this situation.
What exactly does the method fireDetailEvent()?
Thanks in advance!
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new MainFrame("Hello world Swing");
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
MainFrame
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class MainFrame extends JFrame {
private JTextArea textArea;
public MainFrame(String title) {
super(title);
Container c = getContentPane();
c.setLayout(new BorderLayout());
textArea = new JTextArea();
DetailsPanel detailsPanel = new DetailsPanel();
detailsPanel.addDetailListener(new DetailListener() {
public void detailEventOccurred(DetailEvent event) {
String text = event.getText();
textArea.append(text);
}
});
c.add(textArea, BorderLayout.CENTER);
c.add(detailsPanel, BorderLayout.WEST);
}
}
DetailsPanel
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;
public class DetailsPanel extends JPanel {
private static final long serialVersionUID = -5115286206114930420L;
private EventListenerList listenerList = new EventListenerList();
public DetailsPanel() {
Dimension size = getPreferredSize();
size.width = 250;
setPreferredSize(size);
setBorder(BorderFactory.createTitledBorder("Personal details"));
JLabel nameLabel = new JLabel("Name:");
JLabel occupationLabel = new JLabel("Occupation:");
JTextField nameField = new JTextField(10);
JTextField occupationField = new JTextField(10);
JButton addBtn = new JButton("Add");
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
////// First column /////
gc.anchor = GridBagConstraints.LINE_END;
gc.weightx = 0.5;
gc.weighty = 0.5;
gc.gridx = 0;
gc.gridy = 0;
add(nameLabel, gc);
gc.gridy = 1;
add(occupationLabel, gc);
////// Second column /////
gc.anchor = GridBagConstraints.LINE_START;
gc.gridx = 1;
gc.gridy = 0;
add(nameField, gc);
gc.gridy = 1;
add(occupationField, gc);
////// Final row /////
gc.anchor = GridBagConstraints.FIRST_LINE_START;
gc.weightx = 10;
gc.weighty = 10;
gc.gridy = 2;
add(addBtn, gc);
addBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
String occupation = occupationField.getText();
String text = name + ": " + occupation + "\n";
System.out.println(text);
fireDetailEvent(new DetailEvent(this, text));
}
});
}
public void fireDetailEvent(DetailEvent event) {
Object[] listeners = listenerList.getListenerList();
for (int i = 0; i < listeners.length; i += 2) {
if (listeners[i] == DetailListener.class) {
((DetailListener)listeners[i+1]).detailEventOccurred(event);
}
}
}
public void addDetailListener(DetailListener listener) {
listenerList.add(DetailListener.class, listener);
}
public void removeDetailListener(DetailListener listener) {
listenerList.remove(DetailListener.class, listener);
}
}
DetailListener
import java.util.EventListener;
public interface DetailListener extends EventListener {
public void detailEventOccurred(DetailEvent event);
}
DetailEvent
import java.util.EventObject;
public class DetailEvent extends EventObject {
private String text;
public DetailEvent(Object source, String text) {
super(source);
this.text = text;
}
public String getText() {
return text;
}
}
1) What exactly does DetailListener.class?
From the API:
Instances of the class Class represent classes and interfaces in a running Java application.
This is somewhat confusing so let's look at a an example. Calling DetailListener.class provides its Class representation. In this specific case DetailListener.class provides a Class<DetailListener> so it's possible to do this:
Class<DetailListener> cdl = DetailListener.class;
cdl is just another variable similar to how frame is just another variable.
frame happens to be a JFrame which provides some methods, while cdl is a Class<DetailListener> which provides a different set of methods.
cdl's type is a Class<DetailListener> which represents the DetailListener class.
but I still don't understand what it does in this situation
Consider this code:
listenerList.add(DetailListener.class, listener);
listenerList is of type EventListenerList. According to its API, the add(...) method parameters require a Class and a T instance. In this case, the generic T is DetailListener. So far the listener has been registered but it leads into your next question.
#2 What exactly does the method fireDetailEvent()?
When the listener was registered the listenerList keeps an internal array which can be referenced later. The array holds both the Class and the actual listener instance. So invoking
Object[] listeners = listenerList.getListenerList();
provides access to the array. In this case:
listeners[0] = DetailListener.class
listeners[1] = reference to the anonymous inner class instance created from detailsPanel.addDetailListener(...)
So the loop in fireDetailEvent(...) is guaranteed to be a multiple of 2 (0 also works if there are no registered listeners). But listenerList could hold any type of listener, so
if (listeners[i] == DetailListener.class) {
uses the Class to check for equality to make sure it's safe to caste to be able to pass the DetailEvent to the listener (which is the next element in the array). Using == (instead of .equals()) is okay in this context since DetailListener.class always provides the same Class.
What exactly does DetailListener.class?
DetailListener.class is a so-called class literal.
Basically, it is a constant of type Class referring to the
DetailListener type.
You can find more and better explanations about this at
What is a class literal in Java?
and its answers.
What exactly does the method fireDetailEvent()?
Your DetailsPanel class uses an EventListenerList for handling event
listeners and sending events to them.
The comment given in class EventListenerList
gives a detailed description how to use it.
Read this description and you will recognize, that the methods
addDetailListener, removeDetailListener and fireDetailEvent
of your class DetailsPanel are written exactly following this description.
The method fireDetailEvent fires a DetailEvent to all those listeners
which have registered themselves earlier by addDetailListener.
I'm making a frame who needs to show labels in a Scroll Panel, but after I add the labels the scroll don't work.
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(1, 1, 210, 259);
panel.add(scrollPane);
JPanel roomList = new JPanel();
scrollPane.setViewportView(roomList);
roomList.setLayout(null);
int x=0;
for(String l : list) {
JLabel c = new JLabel(l+" "+x);
c.setBounds(new Rectangle(1, 1+x*11, 191, 14));
roomList.add(c);
x++;
}
I'm sure the list has more than 22.
I don't know how to google it!
Your basic problem is, you don't understand how the layout management API works, or how to replace it's functionality when you choose to discard it.
You problem starts here:
roomList.setLayout(null);
There's a lot of work going on in the background which provides a great deal of information to various parts of the API, while on the surface, the layout management API is not complex, the role it plays is.
The JScrollPane will use the component's preferredSize to determine when it should display the scrollbars. Since you've done away with this automated calculation, the JScrollPane has nothing to go on
For more information, have a look at Laying Out Components Within a Container
As a simple example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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);
JScrollPane scrollPane = new JScrollPane(new TestPane());
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
for (int index = 0; index < 100; index++) {
add(new JLabel("Row " + index), gbc);
gbc.gridy++;
}
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(100, 50);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width <= getWidth();
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}
This example implements the Scrollable interface, this is not always required, but is used, for this example, to provide a hint to the JScrollPane about the preferred size of the viewable area it should use, otherwise it will attempt to use the component's preferredSize.
But, as has already been suggested, there are other, simpler and more optimised solutions available to you.
If your information is simple enough, you can use a JList to list a number of values in a vertical manner, see How to use Lists for more details.
If you information is in a more complex structure, you could use a JTable, which provides a row and column style structure. See How to use tables for more information
Have you tried using jLists instead of JScrollPanes ?
They're very easily implemented, look great and work like a charm.
DefaultListModel model = new DefaultListModel();
for(String l : list) {
model.addElement(l);
}
yourList.setModel(model);
Where list is the list with the room data and yourList is the jList.
Say I have a JPanel containing some JTextFields. I would like to perform the same drop action for this JPanel and its children. In other words, I would like the drop action onto the children to be treated the same way as a drop action onto the JPanel.
Is there any other way other than setting the same DropTargetListener for the JPanel and its children?
I know that if I set the TransferHandler of those JTextFields to null, the JPanel will receive the drag and drop event. However, this will destroy the copy and paste functionality of the textfield.
I know that I can intercept mouse events with JLayer. Is there something like this for drag events?
In the end, I added listeners separately to the child components. Because I needed the drop location relative to the parent as well, I used SwingUtilities.convertToPoint() separately on the child components. Which means a lot of different listeners used -- more memory usage. But seems to be the best way for now.
If you want to be able to drop items on a panel but you want any components on the panel to be ignored for dropping purposes you can deactivate the drop target on each of the components added to the panel. You will still be able to cut and paste within them, and there is even a way to initiate a drag from them, but you won't be able to drop anything on them - the drop event goes straight through them to the drop target associated with the panel.
To do this, simply call
component.getDropTarget().setActive(false);
for each component on the panel.
I found this useful when building a calendar panel where I wanted to be able to drag appointments around but drop them on the panel even if it was (partially or completely) covered in other appointments.
Not sure if this is what you had in mind, but, I basically added the same DropTargetListener to all of my components, which meant that it didn't matter where I dragged/dropped the incoming request, all the components triggered the same events...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestDragNDrop100 {
public static void main(String[] args) {
new TestDragNDrop100();
}
public TestDragNDrop100() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements DropTargetListener {
public TestPane() {
DropTarget dt = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
for (int y = 0; y < 4; y++) {
gbc.gridy = y;
for (int x = 0; x < 4; x++) {
gbc.gridx = x;
JTextField field = new JTextField(10);
DropTarget child = new DropTarget(field, DnDConstants.ACTION_COPY_OR_MOVE, this, true);
add(field, gbc);
}
}
}
#Override
public void dragEnter(DropTargetDragEvent dtde) {
System.out.println("DragEnter - " + dtde.getDropTargetContext().getComponent());
}
#Override
public void dragOver(DropTargetDragEvent dtde) {
System.out.println("DragOver - " + dtde.getDropTargetContext().getComponent());
}
#Override
public void dropActionChanged(DropTargetDragEvent dtde) {
System.out.println("dropActionChanged" + dtde.getDropTargetContext().getComponent());
}
#Override
public void dragExit(DropTargetEvent dte) {
System.out.println("dragExit" + dte.getDropTargetContext().getComponent());
}
#Override
public void drop(DropTargetDropEvent dtde) {
System.out.println("drop" + dtde.getDropTargetContext().getComponent());
}
}
}
I should also note. I tested the fields cut/copy/paste functionality and had no issues.
Implement a custom TransferHandler on the container which delegates to its children as appropriate, something along the lines of:
for (int i = 0; i < 5; i++) {
parent.add(new JTextField("item" + i, 20));
};
TransferHandler handler = new TransferHandler() {
#Override
public boolean canImport(TransferSupport support) {
TransferHandler childHandler = getTargetHandler();
return childHandler.canImport(
getTargetSupport(support));
}
protected TransferSupport getTargetSupport(TransferSupport support) {
return new TransferSupport(getTarget(), support.getTransferable());
}
protected TransferHandler getTargetHandler() {
return getTarget().getTransferHandler();
}
protected JComponent getTarget() {
return (JComponent) parent.getComponent(0);
}
#Override
public boolean importData(TransferSupport support) {
return getTargetHandler().importData(getTargetSupport(support));
}
};
parent.setTransferHandler(handler);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What I want to do in my java program is, that when I press the button it displays text in textfield in intervals of time.
i.e I press the button then a jFrame pops up and there is a label which shows text like:
1st second:"1st"
then a time lag of say 1 sec
then 2nd thing: "2nd"
I am a newbie and I tried to Google this problem but I couldn't find a solution even after 3-4 hours
I tried a lot of things: sleep, try n catch...
Please write the answer very simplified.
Here is my code:
In the following code, when the button is pressed, the jFrame comes but has a white screen in it and when the sum ends, its screen turns grey and it shows the answer....
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
See.setVisible(true);//See is the JFrame
t007.setVisible(true);//Label in See
l2.setVisible(true);//TextField in See
int ran, g, d, col, ran2;
double y = 1000 * (Double.parseDouble(t2.getText()));
int x = (int) y;
d = 0;
double c = Math.pow(10, Integer.parseInt(t1.getText()));
col = Integer.parseInt(t3.getText());
for (g = 0; g < col;) {
ran = (int) (Math.random() * (c)); // Random Number Creation Starts
if (ran > (c / 10)) {
g = g + 1;
ran2 = ((int) (Math.random() * 10)) % 2;
if (ran2 == 1) {
ran = ran * (-1);
}
d = d + ran;
if (d < 0) {
ran = ran * (-1);
d = d + (2 * ran);
}
l2.setVisible(true);
t007.setText("" + ran);
System.out.println("" + ran);
jButton6.doClick();
//Pausing (Sleep)
try {
Thread.sleep(x);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
l2.setText("" + d);
}
Swing is a single threaded framework, that is, all interactions and modifications to the UI are expected to occur within the context of the Event Dispatching Thread.
The EDT is responsible for, amongst other things, processing repaint requests.
Anything that stops the EDT from running (like Thread.sleep and looping for a long time) will prevent it from processing the events, virtually "hanging" your application until it becomes unblocked...
Now, I tried to decipher what you program was trying to do...but failed, so instead...I made a pretty counter...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TickOver {
public static void main(String[] args) {
new TickOver();
}
public TickOver() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextField field;
private JButton button;
private int tick;
private Timer timer;
public TestPane() {
field = new JTextField(10);
field.setEditable(false);
button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
tick = 0;
timer.start();
}
});
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field.setText(Integer.toString(++tick));
if (tick > 4) {
timer.stop();
button.setEnabled(true);
}
}
});
timer.setInitialDelay(0);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(field, gbc);
add(button, gbc);
}
}
}
Take a close look at Concurrency in Swing for more details...
You should never sleep in UI thread, as it make the UI lag. As if the process takes time to complete the UI will get stuck and user experience will get hurt.
Use other mechanisms such as a Timer or SwingWorker
Concurrency in Swing
It's very bad practice to sleep the user interface thread. (As this will cause the application to become unresponsive.) You ought to put all this code inside the Run() method of a Runnable instance:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Your code here.
}
});
The problem is that you run your long running loop on the event dispatch thread. But this is the thread that must dispatch all events of the application like mouse or keyboard events but also repaint events that causes your user interface to get repainted every time it gets 'dirty'. That means, while your for-loop is running, the user interface is not repainted nor are any other events processed. Your UI freezes!
Your jButton5ActionPerformed method should return as soon as possible so that the event dispatch thread can process other events. Your long running operation should be run by a separate thread in the background.
A good starting point is the following tutorial about concurrency in Swing:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
Maybe you can use the SwingWorker class to perform your background work:
http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
My program writes text in a JProgressBar. The problem is the text is wider than the JProgressBar's width.
I have already changed the JProgressBar's height to be able to write the text on two lines but I don't want to the change the width.
How to change the JProgressBar's overflow to make the text going back to the next line if it is too wide?
I hope this is clear enough :)
Here is what I would like:
Thanks
EDIT
After #mKorbel reply the result looks like this:
The label works quite fine but why those strips?
My code:
// Construct progress bar
JProgressBar progressBar = new JProgressBar(0, 100);
// Set progressBar color
progressBar.setForeground(new Color(0,176,80));
// Edit progress bar height
Dimension prefSize = progressBar.getPreferredSize();
prefSize.height = 50;
progressBar.setPreferredSize(prefSize);
// Set the layout
progressBar.setLayout(new BorderLayout(5, 5));
// Set progress bar value
progressBar.setValue(38);
// Construct the label
JLabel progressLabel = new JLabel("<html>I have already changed the JProgressBar's height to be able to write the text on two lines but I don't want to the change the width.</html>");
// Set alignment
progressLabel.setHorizontalAlignment(JLabel.CENTER);
progressLabel.setVerticalAlignment(JLabel.CENTER);
// Set the borders
progressLabel.setBorder(new EmptyBorder(15, 15, 15, 15));
// Change the font
font = progressLabel.getFont();
font = font.deriveFont(Font.BOLD, 12);
progressLabel.setFont(font);
// Add label to the progress bar
progressBar.add(progressLabel, BorderLayout.CENTER);
// Add progress bar to the frame
frame.add(progressBar);
the program is developed with Java 6. It seems JLayer is not
available. If I'm wrong, could you provide some code on how to do
this?
could you provide some code on how to do this? --- > JLayer & JProgressBar by #aterai, for more ideas see his blog, for Java6 you can to use JXLayer
or with very similair logics by using GlassPane
some notes
should be used GBC instead of NullLayout
can be nicer with added Icon or transparent background
(by add LayoutManager to JLabel) there can be placed bunch of JComponents with the same effect as for JPanel
for example
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
//https://stackoverflow.com/questions/14560680/jprogressbar-low-values-will-not-be-displayed
public class ProgressSample {
private JFrame frame = new JFrame("GlassPane instead of JLayer");
private JLabel label;
private GridBagConstraints gbc = new GridBagConstraints();
private JProgressBar progressSeven;
public ProgressSample() {
frame.setLayout(new FlowLayout());
frame.add(new JButton("test"));
frame.add(new JCheckBox("test"));
frame.add(new JRadioButton("test"));
// Nothing is displayed if value is lover that 6
JProgressBar progressSix = new JProgressBar(0, 100);
progressSix.setValue(2);
frame.add(progressSix);
// but this works value is higher that 6
progressSeven = new JProgressBar(0, 100);
progressSeven.addComponentListener(new ComponentAdapter() {
#Override
public void componentMoved(ComponentEvent e) {
label.setBounds(
(int) progressSeven.getBounds().getX(),
(int) progressSeven.getBounds().getY(),
label.getPreferredSize().width,
label.getPreferredSize().height);
}
});
progressSeven.setValue(7);
frame.add(progressSeven);
label = new JLabel();
label.setText("<html> Concurency Issues in Swing<br>"
+ " never to use Thread.sleep(int) <br>"
+ " durring EDT, simple to freeze GUI </html>");
label.setPreferredSize(new Dimension(label.getPreferredSize().width, label.getPreferredSize().height));
Container glassPane = (Container) frame.getRootPane().getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(null);
glassPane.add(label, gbc);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
ProgressSample dialogTest = new ProgressSample();
}
}
EDIT
comments
my first thought was using html, but astonishingly (for me) the
progressbar doesn't support it ... by #kleopatra
and
I think my question may not be clear enough. I don't want the text to
exceed the JProgressBar borders. Plus, I don't want to insert manually
line returns (ie no ). I added a picture of what I want. by
#Maxbester
result is to use JProgressBar as Container, put there proper LayoutManager, overlay JProgressBar by JLabel
enhancements, to set EmptyBorder for JLabel, e.g. label.setBorder(new EmptyBorder(15, 15, 15, 15));
EDIT2 (Icon is, can be semi_transparent too, can overlay JProgressBar)
code could be something like as
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
public class JProgressBarWithJLabel {
private JFrame frame = new JFrame("JLabel in JProgressBar");
private JLabel label;
private JProgressBar progressSeven;
public JProgressBarWithJLabel() {
progressSeven = new JProgressBar(0, 100){
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 60);
}
};
progressSeven.setValue(38);
progressSeven.setLayout(new BorderLayout(5, 5));
label = new JLabel();
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
label.setBorder(new EmptyBorder(15, 15, 15, 15));
label.setText("<html>I have already changed the JProgressBar's height "
+ "to be able to write the text on two lines but I don't want "
+ "to the change the width.</html>");
progressSeven.add(label, BorderLayout.CENTER);
frame.add(progressSeven);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JProgressBarWithJLabel();
}
});
}
}
EDIT3:
default stripping for WindowsClassicLookAndFeel (Icon isn't semi_transparent)
The available answers didn't satisfy me. Thus I implemented the following alternative solution for my own needs.
import javax.swing.JProgressBar;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
public class MultilineProgressBar extends JProgressBar
{
private static final String FONT_NAME = "Dialog";
private static final int FONT_SIZE = 12;
private static final int INTERLINE_COEFFICIENT = 2;
private static final int NEWLINE_OFFSET = FONT_SIZE * INTERLINE_COEFFICIENT;
private static final int CENTERING_DIVISOR = 2;
#Override
protected void paintComponent(final Graphics graphics)
{
super.paintComponent(graphics);
final String componentString = getString();
int i = componentString.indexOf('\n');
if (i == -1)
return;
// Draw first line of the component's string
String currentString = componentString.substring(0, i);
Rectangle2D stringBounds = getFontMetrics(getFont()).getStringBounds(currentString, graphics);
graphics.setFont(new Font(FONT_NAME, Font.BOLD, FONT_SIZE));
graphics.setColor(Color.WHITE);
graphics.drawString(currentString,
(int) (getWidth() - stringBounds.getWidth()) / CENTERING_DIVISOR,
(int) (getHeight() - stringBounds.getHeight()) / CENTERING_DIVISOR);
++i;
if (i >= componentString.length())
return;
// Draw second line of the component's string
currentString = componentString.substring(i);
stringBounds = getFontMetrics(getFont()).getStringBounds(currentString, graphics);
graphics.drawString(currentString,
(int) (getWidth() - stringBounds.getWidth()) / CENTERING_DIVISOR,
(int) ((getHeight() - stringBounds.getHeight()) / CENTERING_DIVISOR) + NEWLINE_OFFSET);
}
}