Discussions
Categories
- 196.8K All Categories
- 2.2K Data
- 239 Big Data Appliance
- 1.9K Data Science
- 450.3K Databases
- 221.7K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 31 Multilingual Engine
- 550 MySQL Community Space
- 478 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3K ORDS, SODA & JSON in the Database
- 544 SQLcl
- 4K SQL Developer Data Modeler
- 187K SQL & PL/SQL
- 21.3K SQL Developer
- 295.8K Development
- 17 Developer Projects
- 138 Programming Languages
- 292.5K Development Tools
- 107 DevOps
- 3.1K QA/Testing
- 646K Java
- 28 Java Learning Subscription
- 37K Database Connectivity
- 155 Java Community Process
- 105 Java 25
- 22.1K Java APIs
- 138.1K Java Development Tools
- 165.3K Java EE (Java Enterprise Edition)
- 18 Java Essentials
- 160 Java 8 Questions
- 86K Java Programming
- 80 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 204 Java User Groups
- 24 JavaScript - Nashorn
- Programs
- 439 LiveLabs
- 38 Workshops
- 10.2K Software
- 6.7K Berkeley DB Family
- 3.5K JHeadstart
- 5.7K Other Languages
- 2.3K Chinese
- 171 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 232 Portuguese
How to display "Loading data..." to the user
Hi I have a complex ui screen.
In that there is a panel, which displays a graph to the user and it updates to a different graph, depepnding upon the user clicks.
I need to get a lot of data from the backend and then change the graph to the user.
When i am loading hte data, i need to change the panel display to indicate that the data is being acquired and processed.
I dont want to use the cardlayout,
i want to know what other appoaches i can use to show the information to the user.
One of the things i have beein thinking about is dim the current panel and show a message box inside the panel i am updating.
Does anyone know how i can change the alpha(and make it dimmer) in case of a JPanel and throw a small popupwindow inside th epanel to display the message?
any clue or hint is greately appreciated,
thanks,
vani
In that there is a panel, which displays a graph to the user and it updates to a different graph, depepnding upon the user clicks.
I need to get a lot of data from the backend and then change the graph to the user.
When i am loading hte data, i need to change the panel display to indicate that the data is being acquired and processed.
I dont want to use the cardlayout,
i want to know what other appoaches i can use to show the information to the user.
One of the things i have beein thinking about is dim the current panel and show a message box inside the panel i am updating.
Does anyone know how i can change the alpha(and make it dimmer) in case of a JPanel and throw a small popupwindow inside th epanel to display the message?
any clue or hint is greately appreciated,
thanks,
vani
Comments
-
You could have a non-opaque JPanel above your panel in an Overlay Layout and draw on it with an AlphComposite for a "dimming" affect. Also check out the JProgressBar and ProgressMonitor classes. The Swing tutorial has a page in which these are discussed: How to Use Progress Bars.
-
Another option is using a glass pane above the app and do the same thing that crwood mentioned (alpha composite painting, JProgressBars, etc).
-
Personally, I like crwood's suggestion. Extend JPanel, override the paintComponent method, and paint a partially transparent rectangle over the entire thing.
However, beware of this problem: Most Component subclasses have asynchronous repaint methods (such as JPanel and JLabel). That means that the work of actually painting each pixel runs in another thread, which usually doesn't finish until other operations are complete. In other words, your screen dimming and loading data message may not occur until after the data has already been loaded.
To solve this problem, call the Components's paintImmediately method right after you display the it. That forces the paint operation to be executed in the same thread, so the desired action will occur BEFORE the data starts loading (which is the behavior you are trying to create). Note, that JProgressBar is immune from this problem.
I fought this issue for hours, so I'm just giving you the heads up.
Hope it helps,
Bill
PS: A lot more info is available here: http://java.sun.com/products/jfc/tsc/articles/painting/ . Pay attention to the stuff about synchronization and threads. -
Personally, I like crwood's suggestion. Extend JPanel, override the paintComponent method....That is what a GlassPane is for. You create the panel as described. Then you use:
frame.setGlassPane(...);To solve this problem, call the Components's paintImmediately method...The real problem is that you are trying to execute a long running task in the GUI Event Thread. The long running task should execute in its own Thread so the GUI is free to repaint itself.How to display "Loading data..." to the userIf you really want to display some text, then you should probably be using an indeterminate progress bar since is displays an actual window with borders. If you just try to write text on the JPanel or GlassPane, you never know what you will be painting over unless you customize the painting to fill in the background before you write the text. -
That is what a GlassPane is for. You create the panelThe glass pane will work fine too. I'd choose the overlay approach simply because it allows me to create a JPanel subclass DimmableJPanel that doesn't rely on a JFrame to help. For the benefit of the OP, heres a link that explains the glass pane: http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html
as described. Then you use:
frame.setGlassPane(...);The real problem is that you are trying to execute aYep. Thats why repaint starts a new thread. But in this case, the text has to be painted before starting a new task, hence the call to paintImmediately. JProgressBar does the same thing, because progress bars have to be updated in real time.
long running task in the GUI Event Thread. The long
running task should execute in its own Thread so the
GUI is free to repaint itself.If you really want to display some text, then youRight. But if you don't want to use an indeterminate progress bar, you can recreate that same behavior with a JLabel and paintImmediately. (Yes, you do have to accept responsibility for the background if you don't repaint the entire JPanel.)
should probably be using an indeterminate progress
bar since is displays an actual window with borders.
If you just try to write text on the JPanel or
GlassPane, you never know what you will be painting
over unless you customize the painting to fill in the
background before you write the text.
- Bill -
I'd choose the overlay approach simply because it allows me toDon't understand this statement. How do you show a DimmableJPanel overtop of an existing panel?
create a JPanel subclass DimmableJPanel that doesn't rely on a JFrame to helpBut in this case, the text has to be painted before starting a new task, hence the call to paintImmediately.There is no need to use paintImmediately. You update the GUI component. Then you start a separate Thread for the long running task. The GUI is free to repaint the label or whatever. Yes, technically you may have to wait milliseconds (over using paintImmediately), but the user will see no difference. paintImmediately is not recommended to be used. The RepaintManager manages paint requests and consolidates multiple paint requests into one for efficiency reasons. Using paintImmediately overrides the default behaviour and is not needed in this situation.Right. But if you don't want to use an indeterminate progress bar, youThe point is not to recreate code, but to use the code that is available.
can recreate that same behavior with a JLabel and paintImmediately.
I was also suggesting that a progress bar is a dialog that only covers a certain amount of space. A disable panel would cover the entire frame. So it depends on the look that the user is going for.
Here is an example of a disable GlassPane:import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; public class DisabledGlassPane extends JComponent implements KeyListener { private final static Color DEFAULT_BACKGROUND = new Color(128, 128, 128, 128); private final static Border MESSAGE_BORDER = new EmptyBorder(10, 10, 10, 10); private JLabel message = new JLabel(); public DisabledGlassPane() { setOpaque( false ); setBackground( DEFAULT_BACKGROUND ); setLayout( new GridBagLayout() ); add(message, new GridBagConstraints()); message.setOpaque(true); message.setBorder(MESSAGE_BORDER); // Disable Mouse, Key and Focus events for the glass pane addMouseListener( new MouseAdapter() {} ); addMouseMotionListener( new MouseMotionAdapter() {} ); addKeyListener( this ); setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET ); setFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET ); } protected void paintComponent(Graphics g) { g.setColor( getBackground() ); g.fillRect(0, 0, getSize().width, getSize().height); } public void setBackground(Color background) { super.setBackground( background ); Color messageBackground = new Color(background.getRed(), background.getGreen(), background.getBlue()); message.setBackground( messageBackground ); } public void keyPressed(KeyEvent e) { e.consume(); } public void keyTyped(KeyEvent e) { e.consume(); } public void keyReleased(KeyEvent e) { e.consume(); } public void activate(String text) { if (text != null && text.length() > 0) { message.setVisible( true ); message.setText( text ); message.setForeground( getForeground() ); } else message.setVisible( false ); setVisible( true ); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); requestFocusInWindow(); } public void deactivate() { setCursor(null); setVisible( false ); } public static void main(String[] args) { final DisabledGlassPane glassPane = new DisabledGlassPane(); glassPane.setBackground( new Color(255, 128, 128, 128) ); glassPane.setForeground( Color.WHITE ); final JButton button = new JButton( "Click Me" ); button.setMnemonic('c'); button.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { glassPane.activate("Please Wait..."); Thread thread = new Thread() { public void run() { try { this.sleep(5000); } catch (InterruptedException ie) {} glassPane.deactivate(); } }; thread.start(); } }); JFrame frame = new JFrame(); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setGlassPane( glassPane ); frame.getContentPane().add(new JLabel("NORTH"), BorderLayout.NORTH ); frame.getContentPane().add( button ); frame.getContentPane().add(new JTextField(), BorderLayout.SOUTH); frame.setSize(300, 300); frame.setLocationRelativeTo( null ); frame.setVisible(true); } }
-
hi codebook, using a glasspane is not a viable option for me, because i want to display the Loading data on only one of the panels in the frame.
vani -
Hi All,
i went through all of your reply and unfortunately only a part of the screen is being updated and only that panel need to show the "Loading Data..." message not the whole screen. So i can not use the glass pane nad block the whole screen.
If some one knows how to update only a part of the screen, that would be very helpful.
vani -
Is there a way to set the Z order of the Panels in the Overlay layout?
How can i choose the Panel whoich should be showing on top?
thanks -
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DimOverlay { DimmerPanel dimmerPanel; private JPanel getContent() { dimmerPanel = new DimmerPanel(); JPanel content = new JPanel(new BorderLayout()); JLabel label = new JLabel("graphical data", JLabel.CENTER); content.add(label); JPanel panel = new JPanel(); OverlayLayout overlay = new OverlayLayout(panel); panel.setLayout(overlay); panel.add(dimmerPanel); panel.add(content); return panel; } private void reload() { Thread thread = new Thread(new Runnable() { public void run() { int count = 0; boolean workAway = true; while(workAway && count <= 10) { try { Thread.sleep(1000); } catch(InterruptedException e) { workAway = false; } System.out.println("count = " + count++); } dimmerPanel.clearView(); } }); thread.setPriority(Thread.NORM_PRIORITY); thread.start(); dimmerPanel.dimView(); } private JPanel getControl() { JButton reload = new JButton("reload"); reload.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { reload(); } }); JPanel panel = new JPanel(); panel.add(reload); return panel; } public static void main(String[] args) { DimOverlay test = new DimOverlay(); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.getContentPane().add(test.getContent()); f.getContentPane().add(test.getControl(), "Last"); f.setSize(400,400); f.setLocation(200,200); f.setVisible(true); } } class DimmerPanel extends JPanel { float alpha = 0.0f; public DimmerPanel() { setOpaque(false); } public void dimView() { alpha = 0.25f; repaint(); } public void clearView() { alpha = 0.0f; repaint(); } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha); g2.setComposite(ac); g2.setPaint(Color.gray); g2.fillRect(0, 0, getWidth(), getHeight()); } }
This discussion has been closed.