I'm starting to teach myself Java, and it's possible my reach doth exceed my grasp. Still, that's the best way to learn, right?
I'm trying to play around with simple graphics. I've found various resources on how to draw shapes into a JFrame, and made them work, but as far as I can tell the code always needs to go inside the paint method, which gets called automatically, which means I can't figure out how to go about passing it arguments.
What I'm trying to do is write some code that can take co-ordinates as arguments, and then place a simple shape (let's go with a 10x10 pixel square) at those co-ordinates. I feel sure that must be something that's possible, but I cannot for the life of me work out how.
Code so far, incorporating help from both #resueman and #Mikle:
public class Robots {
public static void main(String[] args) {
Window window = new Window();
window.Window();
new PlayArea();
Point p = new Point(50,50);
Entity player1 = new Entity();
player1.Entity(p);
}
}
public class Window extends JFrame{
int x;
int y;
public void Window(){
Window window = new Window();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setTitle("Robots");
window.setSize(800,600);
window.getContentPane().add(new PlayArea());
window.setLocationRelativeTo(null);
window.setBackground(Color.white);
window.setVisible(true);
}
}
public class PlayArea extends JComponent{
// I keep all added and displayed entities here for easier access
public final List<Entity> entities = new ArrayList<Entity> ();
public PlayArea(){
super();
}
public void addEntity(final Entity entity){
//add new entity and repaint area
entities.add(entity);
}
#Override
protected void paintComponent (final Graphics g)
{
super.paintComponent (g);
// Painting entities
final Graphics2D g2d = (Graphics2D) g;
for (final Entity entity : entities)
{
g2d.setPaint ( Color.BLACK );
g2d.fill (getEntityShape (entity));
}
}
protected Shape getEntityShape ( final Entity entity )
{
// Simple entity shape, you can replace it with any other shape
return new Rectangle ( entity.entPos.x - 5, entity.entPos.y - 5, 10, 10 );
}
}
public class Entity extends JComponent{
protected Point entPos = null;
public void Entity(Point p){
entPos = p;
repaint();
}
#Override
public void paintComponent (Graphics g){
super.paintComponent(g);
if (entPos != null){
g.fillRect(entPos.x, entPos.y, 10,10);
}
}
}
I want to be able to create an object in the Entity class, and put it in the window at the x,y co-ordinates.
I will eventually want to be able to move Entities around, but I'll work that one out once I've figured out how to draw them in the first place!
Still not drawing anything in the window. I'm probably missing something really obvious though.
There are a lot of possible approaches to solve your task.
Here are the first two options which come to mind:
Use a custom component and paint all Entity objects in it
This one will be easy and fast to implement.
Implementing entities drag also won't be a big issue. There are also a few options how painting can be done here. This approach is good in case you are going to have just a few simple elements painted on the area and don't want to make your code too complicated.
Paint each Entity on a separate component, and place them using layout managers
This is harder to achieve, but it will use much less resources and will be painted faster due to Swing repainting optimizations. This approach is much better if you are aiming at a large amount of elements or large area size. But that might be an overkill for your case.
Here is a simple example of the 1st approach (including entities drag):
public class SingleComponent extends JFrame
{
public SingleComponent () throws HeadlessException
{
super ();
setTitle ( "Robots" );
setBackground ( Color.white );
// Adding our custom component into the frame
getContentPane ().add ( new EntitiesArea () );
setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
setSize ( 800, 600 );
setLocationRelativeTo ( null );
setVisible ( true );
}
public class Entity
{
int x;
int y;
public Entity ( final int x, final int y )
{
this.x = x;
this.y = y;
}
}
public class EntitiesArea extends JComponent
{
// I keep all added and displayed entities here for easier access
public final List<Entity> entities = new ArrayList<Entity> ();
public EntitiesArea ()
{
super ();
// Adding mouse adapter that will add/drag entities
final MouseAdapter mouseAdapter = new MouseAdapter ()
{
// Currently dragged entity
private Entity dragged = null;
#Override
public void mousePressed ( final MouseEvent e )
{
// Looking for entity under mouse
Entity underPoint = null;
for ( final Entity entity : entities )
{
if ( getEntityShape ( entity ).contains ( e.getPoint () ) )
{
underPoint = entity;
break;
}
}
// Either dragging existing entity or adding new one
if ( underPoint != null )
{
dragged = underPoint;
}
else
{
addEntity ( new Entity ( e.getX (), e.getY () ) );
}
}
#Override
public void mouseDragged ( final MouseEvent e )
{
if ( dragged != null )
{
// Change entity coordinate and repaint area
dragged.x = e.getX ();
dragged.y = e.getY ();
repaint ();
}
}
#Override
public void mouseReleased ( final MouseEvent e )
{
if ( dragged != null )
{
dragged = null;
}
}
};
addMouseListener ( mouseAdapter );
addMouseMotionListener ( mouseAdapter );
}
public void addEntity ( final Entity entity )
{
// Add new entity and repaint area
entities.add ( entity );
repaint ();
}
#Override
protected void paintComponent ( final Graphics g )
{
super.paintComponent ( g );
// Painting entities
final Graphics2D g2d = ( Graphics2D ) g;
for ( final Entity entity : entities )
{
g2d.setPaint ( Color.BLACK );
g2d.fill ( getEntityShape ( entity ) );
}
}
protected Shape getEntityShape ( final Entity entity )
{
// Simple entity shape, you can replace it with any other shape
return new Rectangle ( entity.x - 20, entity.y - 20, 40, 40 );
}
}
public static void main ( final String[] args )
{
new SingleComponent ();
}
}
I didn't add any repaint optimizations to this example to make it as simple as it could be, but keep in mind that any action in this example repaints the whole area and forces each entity to be painted from a scratch. This won't even be noticeable until a large amount of elements appear on the area, but make sure you take care of optimized repaint(...) calls later as this is one of the things that make Swing so fast and so good.
If you want to draw independently of the presentation / rendering, you can draw on a BufferedImage for example. You can acquire a Graphics object associated with the BufferedImage with its getGraphics() and createGraphics() methods.
And if later you want to display this, you can with the Graphics.drawImage() methods inside JComponent.paintComponent().
Related
I have a JPanel that I draw upon. The shapes I draw are some objects stored in a list. I would like to register MouseOvers over these drawn objects. What I am currently doing is adding a MouseMotionListener that checks the list of objects for a hit every time the mouse moves. This is of course pretty inefficient once there are a lot of objects. Is there a better way to check for MouseOvers than just checking all the objects every time the mouse moves?
Here is a minimal example:
class Ui.java:
public class Ui {
private static JFrame frame;
private static DrawPanel drawPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> { createGui();
});
}
private static void createGui() {
frame = new JFrame("Test");
drawPanel = new DrawPanel();
frame.setContentPane(drawPanel);
frame.pack();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
class SomeObject.java:
public class SomeObject {
//class that represents some object that will be drawn. note that this is
//just a minmal example and that in my actual application, there are
//other aspects and functions to this class that have nothing to do with drawing.
//This is just kept small for the sake being a minimal example
private String id;
private Point2D origin;
private int length;
private int height;
public SomeObject(String id, Point2D origin, int length, int height) {
this.id = id;
this.origin = origin;
this.length = length;
this.height = height;
}
public String getId() {
return id;
}
public Point2D getOrigin() {
return origin;
}
public int getLength() {
return length;
}
public int getHeight() {
return height;
}
}
class CustomMouseMotionListener.java:
public class CustomMouseMotionListener implements java.awt.event.MouseMotionListener {
public CustomMouseMotionListener() { }
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
for (SomeObject object: DrawPanel.objectsToDraw) {
Shape s = new Rectangle((int)object.getOrigin().getX(), (int)object.getOrigin().getY(), object.getLength(), object.getHeight());
if (s.contains(e.getPoint())) {
System.out.println("hit: " + object.getId());
}
}
}
}
class DrawPanel.java:
public class DrawPanel extends JPanel {
public static List<SomeObject> objectsToDraw = new ArrayList<>();
public DrawPanel() {
objectsToDraw.add( new SomeObject("a", new Point2D.Float(20,1), 20,20));
objectsToDraw.add( new SomeObject("b", new Point2D.Float(20,45), 20,20));
addMouseMotionListener(new CustomMouseMotionListener());
setFocusable(true);
setVisible(true);
grabFocus();
}
protected void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
super.paintComponent(g2D);
for (SomeObject object: objectsToDraw) {
g.drawRect((int)object.getOrigin().getX(), (int)object.getOrigin().getY(), object.getLength(), object.getHeight());
}
}
}
Instead of using your SomeObject class, i recommend using Shape or Area. The whole purpose of SomeObject seems to be to be turned into a Shape anyway, right? Not only that, but with an ArrayList of Shapes, you can eliminate creating rectangles for your shapes in every mouseMove.
BTW, years ago I put together a package for treating Areas like 1st class Components. You can see this here: https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/shape/
(Start with AreaManager and AreaModel). Area has some advantages and disadvantages: Advantages: Easy to manage as a group, fairly easy to test if they are overlapping. Disadvantage: You lose the information about how the Area was constructed (ex. Polygon points, circle radius, etc)
You've already taken this a long way, so kudos to you. This answer is (a) responding to your question about efficiency, but also pointing you in some ways you could choose to go
There is more to SomeObject than just being drawn, so I think I can't just replace it with Shape,
Then you keep a Rectangle instance as part of your SomeObject class, instead of your Point and length/height variables.
Then you modify your methods to return the values from the Rectangle.
This will prevent you from continually creating new Rectangle instances, make the process more memory efficient and reducing garbage collection.
But, you should also be able to extend the Rectangle class and add your extra functionality in the same way that you extend JPanel to add custom painting logic.
Repaint is not calling PaintComponent.
I tried to call it from another method of the Try class too but it did not work out.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class Try extends JPanel {
int i =0;
#Override
public void paintComponent(Graphics g){
//super.paintComponent(g);
System.out.println("hey");
}
public static void main(String[] args) {
JFrame f=new JFrame();
Try t = new Try();
f.setSize(500,600);//400 width and 500 height
Container contentPane = f.getContentPane();
contentPane.add(new PaintComponent());
f.setVisible(true);//making the frame visible
while(true){
t.repaint();
}
}
}
There are multiple issues some of which are mentioned by #trashgod in comments.
You are calling repaint on the instance which you did NOT add to the content pane - you have a different one there (actually, you have something completely different there - new PaintComponent()).
Do not remove super.paintComponent ( g ); unless you clean up the area on your own (pretty much fill the whole component background if it is opaque), otherwise you will get visual glitches on such components upon repaint.
You are spamming repaint operations which is extremely bad, make at least some delay between the repaints giving Swing time to perform the repaints. The best case is if you repaint component only when it actually will display something different visually. If you need to update the view all the time - at least limit it to 30-60 frames (repaints) per second. Also, some internal Swing optimizations might "eat" some of the repaint calls, so expect that you might not see as many paintComponent calls as a number of repaints you call on the component.
You are working with Swing components outside of Event Dispatch Thread (shortly EDT) which might cause issues. Make sure you always use it to create Swing components and call any methods on them. SwingUtilities helps with that.
Any heavy operations that take a long time (or unknown time) to be completed should be executed outside of EDT, otherwise, your UI will simply hang while you are waiting for that operation to complete because all UI updates are performed on EDT and not anywhere else.
Considering all I said above, this is how your example should look like:
public class Try extends JPanel
{
#Override
public void paintComponent ( final Graphics g )
{
super.paintComponent ( g );
final Graphics2D g2d = ( Graphics2D ) g;
g2d.drawString ( Long.toString ( System.currentTimeMillis () ), 25, 35 );
System.out.println ( "repainted" );
}
public static void main ( final String[] args )
{
SwingUtilities.invokeLater ( new Runnable ()
{
#Override
public void run ()
{
final JFrame f = new JFrame ();
final Try t = new Try ();
f.getContentPane ().add ( t );
f.setSize ( 500, 600 );
f.setVisible ( true );
new Thread ( new Runnable ()
{
#Override
public void run ()
{
try
{
while ( true )
{
t.repaint ();
Thread.sleep ( 25 );
}
}
catch ( final InterruptedException e )
{
//
}
}
} ).start ();
}
} );
}
}
Hope that clarifies it a bit for you.
There is also SwingWorker class that helps to perform long-running tasks in Swing, but I didn't use it here to keep the example as simple as possible.
Also a side note - you do not need to call repaint () within EDT because it sends the repaint request to EDT on its own, so that method is safe to use on any thread (like I do in the example).
I has a MouseAdapter that I use to drag a window around simply by clicking its background, like so:
public class Dragger extends MouseAdapter{
private Point offset;
private Window window;
public Dragger(Window w){
window = w;
}
#Override
public void mousePressed(MouseEvent e){
offset = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e){
Point m = e.getLocationOnScreen();
window.setLocation(m.x - offset.x, m.y - offset.y);
}
}
Simple as, right?
And I add it to the JFrame I'm using it on (I'm using it on a JDialogUE as well, hence the 'Window':
// Drag Listeners
Dragger dr = new Dragger(this);
addMouseListener(dr);
addMouseMotionListener(dr);
The drag (currently) only works when I construct a new Dragger, then add it as both a MouseListener and MouseMotionListener.
Is there a nicer, prettier, more elegant, more traditionally sound, more professionally robust, so it goes, way of doing it in just one method?
In such cases I would suggest writing helper static methods within the Dragger class:
public class Dragger extends MouseAdapter
{
private Point offset;
private Window window;
public Dragger ( final Window w )
{
window = w;
}
#Override
public void mousePressed ( final MouseEvent e )
{
offset = e.getPoint ();
}
#Override
public void mouseDragged ( final MouseEvent e )
{
final Point m = e.getLocationOnScreen ();
window.setLocation ( m.x - offset.x, m.y - offset.y );
}
public static void install ( final Window window )
{
final Dragger dr = new Dragger ( window );
window.addMouseListener ( dr );
window.addMouseMotionListener ( dr );
}
public static void uninstall ( final Window window )
{
for ( final MouseListener mouseListener : window.getMouseListeners () )
{
if ( mouseListener instanceof Dragger )
{
window.removeMouseListener ( mouseListener );
}
}
for ( final MouseMotionListener mouseMotionListener : window.getMouseMotionListeners () )
{
if ( mouseMotionListener instanceof Dragger )
{
window.removeMouseMotionListener ( mouseMotionListener );
}
}
}
}
And then simply call Dragger.install(window) and Dragger.uninstall(window).
Not sure whether it is a good approach or not, but it takes less space and might also ensure that you don't add Dragger twice if you add some more checks into install method - of course if you don't want to have Dragger installed twice on the same window.
Also in that case you don't need to look in your code for the usage of this class since you are sure how it will be installed and uninstalled and can change that behavior in one place instead of modifying lots of add*Listener calls.
I have set up an area where a jslider should alter the delay of some dots in a jpanel here
JSlider source = (JSlider)e.getSource();
if (source == speedSlider) {
if (source.getValueIsAdjusting()) {
GraphicsDisplay.delay += 100000;
}
}
The delay is put into affect by the following
public static boolean stop = true ;
public static long delay = 3000000 ;
public void paint ( Graphics g2 ) {
//code making dots up here...
int a;
if ( !stop ) {
for ( a=0; a<delay; a++ ) ;
moveDot ( ) ;
}
repaint();
}
I can't get the slider to do anything. And I know it has something to do with
if (source.getValueIsAdjusting()) {
GraphicsDisplay.delay += 100000;
}
The problem isn't with the slider, it's with your painting...
Basically, you are blocking the Event Dispatching Thread, preventing it from actually painting...
public void paint ( Graphics g2 ) {
// Let's ignore the fact that you haven't called super.paint here...
//code making dots up here...
int a;
if ( !stop ) {
// Block the EDT, stop all painting and event processing until this for
// exist...
for ( a=0; a<delay; a++ ) ;
moveDot ( ) ;
}
// This is a very bad idea inside any paint method...
repaint();
}
Basically, what's happening, is the RepaintManager is consolidating most of your repaint requests down to as few events as possible, in order to maintain performance. So while you "block" the EDT, you paint requests are been queued, but not processed, the repaint manager is making decisions that may also consolidate those requests down to a few events in order to maintain performance.
A better solution would be to use a Swing Timer. See How to Use Swing Timers
private javax.swing.Timer timer;
//...
timer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
moveDot();
repaint();
}
});
timer.start();
//...
if (source.getValueIsAdjusting()) {
timer.stop();
timer.setDelay(source.getValue());
timer.start();
}
Your use of static variables is also a little scary...
ps- I forgot to mention, you should avoid overriding paint and instead use paintComponent, making sure you call super.paintComponent first...See Perfoming Custom Painting
Ok, I have the following code.
public class MyProgressBar extends JPanel implements MyData, Serializable {
/**
*
*/
public static final int MAX = 10000;
public static final int WIDTH = 400;
public static final int HEIGHT = 75;
private JProgressBar MyBar = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
private JFrame MyFrame = new JFrame();
private int MyValue = 0;
private Thread MyThread = new Thread( new ProgressThread() );
public MyProgressBar() {
add(MyBar);
int x = ( MyData.SCREEN.width / 2 ) - ( WIDTH / 2);
int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);
this.setBounds( x, y, WIDTH, HEIGHT );
MyFrame.setBounds( x, y, WIDTH, HEIGHT );
MyFrame.setUndecorated(true);
MyFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setVisible(false);
MyFrame.getContentPane().setLayout(null);
MyBar.setStringPainted( true );
MyBar.setBorderPainted( true );
MyBar.setValue( 0 );
MyBar.setBounds( 0, 0, WIDTH, HEIGHT );
MyFrame.add( MyBar );
MyFrame.pack();
MyFrame.repaint();
}
public void MyUpdateBar() {
MyBar.setValue( MyValue );
MyBar.repaint();
MyFrame.repaint();
this.repaint();
//dbug.Message( "MYPROGRESSBAR", "MyUpdateBar", "Value is %3.2f %d", MyBar.getPercentComplete(), MyValue );
}
public void MySetValue( int percent ) {
MyValue = (int)( MAX * ( (double)percent / 100.0 ) );
MyUpdateBar();
//dbug.Message( "MYPROGRESSBAR", "MySetValue", "Value is %3.2f %d percent was %d", MyBar.getPercentComplete(), MyValue, percent );
}
public void CreateAndShow () {
MyFrame.setVisible(true);
MyThread.start();
}
public void HideAndClear () {
MyThread.stop();
//frame.setVisible(false);
}
class ProgressThread implements Runnable {
public void run() {
EventQueue.invokeLater(new Runnable() {
public void run() {
while( MyValue < MyBar.getMaximum() ) {
MyBar.setValue( MyValue );
MyBar.repaint();
MyFrame.repaint();
dbug.Message( "MYPROGRESSBAR", "THREAD", "Value is %3.2f %d", MyBar.getPercentComplete(), MyValue );
}
}
});
}
}
}
As you can see, I have created a class that I want to have show the progress. What happens is I instantiate the class. Load my XML file, then as I am parsing data, I am calling to update the MyValue which I see when I let my dbug messages come out. However, the bar itself does not even show until it is 100% complete. I have read about threading and following someone else's example and if I left it as his example it worked. If I made a few tweaks (changing a loop in the thread to populate the setvalue of the progress bar to read a value) it does not even show until it is 100.
What did I do wrong?
Thanks!
You thread executes SwingUtilities.invokeLater. You're effectively running on Swing's Event Dispatch Thread. Not sure what are you trying to achieve. But it looks like you are blocking EDT and your while loop is not updated as MySetValue is not executed.
Consider using SwingWorker for lengthy operations. How to Use Progress Bars demonstrates use of SwingWorker with JProgressBar.
Make sure you call setValue method from the Event Dispatch Thread. You can use SwingUtilities.invokeLater for that. Read more about Threads and Swing.
Consider this simplified sample:
public static void main(String[] arguments) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
final JProgressBar bar = new JProgressBar(0, 100);
Thread t = new Thread(){
public void run(){
for(int i = 0 ; i < 100 ; i++){
final int percent = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
bar.setValue(percent);
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
};
frame.add(bar);
frame.pack();
frame.setVisible(true);
t.start();
}
The problem is that you use a loop in the EDT that updates the progress. Until that loop exits, the EDT cannot dispatch events (like repaint, revalidate, invokeLater, mouse events, key events, etc...) preventing it from refreshing the progress bar.
You should try to find a way to let the EDT dispatch its events between each update of the progress bar. Ideally, you move your "work" outside the EDT with a SwingWorker, and meanwhile the progressbar get updated through property change listeners in the EDT.
For your information, in Java, methods and variables starts with a lower case letter. Your code is really hard to read for others.
So, I tried to follow the tutorial and here is where I am at.
Ok, I have tried following tutorials but I keep getting lost somewhere. What I need is a class that creates and displays a progress bar (JProgressBar) that I can set the value of as I iterate over data loaded from a file and place into the database memory. My problems come that every example I have found has some kind of counter that fills the progress bar and executes from a "main" function. Every time I alter that tutorial to be a class that I can call at will and display the bar, I do not get the bar showing (ie the frame comes up but the bar does not even look like it is added to the frame until after the iteration is done). I have tried using SwingUtilities.invokeLater and SwingWorker (lastest attempt at class below) all having the same issue. To make matters worse, I can do a dbug.myMessage (basically sends to System.out) and see a message that shows that the bar is changing in memory just not showing. I am obviously missing something probably simple but I can't think of what it is.
Oh, one other thing, if I leave the tutorial as is (http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/ProgressBarDemo2Project/src/components/ProgressBarDemo2.java) and just change the main to a createAndShow method, it works but of course it does not do what I need it to do.
I did post another question about this but have altered the class so much I thought it best to post a new question.
So, here is my altered code that does not seem to work:
public class MyProgressBar extends JPanel implements PropertyChangeListener,
MyData,
Serializable {
/**
*
*/
private static final long serialVersionUID = -1632492668549544408L;
private MyDebug dbug = new MyDebug( MyData.MYDEBUGCHECK.MYPROGRESSBAR.getOn() );
public static final int MAX = 100;
public static final int WIDTH = 400;
public static final int HEIGHT = 75;
private JProgressBar myBar = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
private JFrame myFrame = new JFrame();
public Task task;
class Task extends SwingWorker<Void, Void> {
public int myValue = 0;
#Override
public Void doInBackground() {
//Initialize progress property.
setProgress(0);
while (myValue < 100) {
//Make random progress.
//myValue += random.nextInt(10);
setProgress( Math.min( myValue, 100 ) );
dbug.myMessage( "MYPROGRESSBAR", "doInBackground", "Value is %3.2f %d", myBar.getPercentComplete(), myValue );
myBar.repaint();
}
return null;
}
public void done() {
}
public void mySetValue( int percent ) {
myValue = (int)( MAX * ( (double)percent / 100.0 ) );
dbug.myMessage( "MYPROGRESSBAR", "mySetValue", "Value is %3.2f %d percent was %d", myBar.getPercentComplete(), myValue, percent );
}
}
public MyProgressBar() {
add(myBar);
int x = ( MyData.SCREEN.width / 2 ) - ( WIDTH / 2);
int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);
this.setBounds( x, y, WIDTH, HEIGHT );
myFrame.setBounds( x, y, WIDTH, HEIGHT );
myFrame.setUndecorated(true);
myFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setVisible(false);
myFrame.getContentPane().setLayout(null);
myFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
myBar.setStringPainted( true );
myBar.setBorderPainted( true );
myBar.setValue( 0 );
myBar.setBounds( 0, 0, WIDTH, HEIGHT );
myBar.addPropertyChangeListener( this );
myFrame.add( myBar );
//Create and set up the content pane.
//JComponent newContentPane = new MyProgressBar();
JComponent newContentPane = myBar;
newContentPane.setOpaque(true); //content panes must be opaque
myFrame.setContentPane(newContentPane);
myFrame.pack();
}
public void createAndShow () {
//Display the window.
myFrame.setVisible(true);
myFrame.repaint();
}
public void hideAndClear () {
//myFrame.setVisible(false);
}
#Override
public void propertyChange(PropertyChangeEvent args) {
dbug.myMessage( "MYPROGRESSBAR", "propertyChange", "Value is %s", args.getPropertyName() );
if ( "progress" == args.getPropertyName() ) {
int progress = (Integer) args.getNewValue();
//myBar.setValue(progress);
}
}
public void start () {
//Instances of javax.swing.SwingWorker are not reusuable, so
//we create new instances as needed.
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
}
}
The below snippet updates the progress bar while in progress
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue((int)percentage);
//below code to update progress bar while running on thread
progressBar.update(progressBar.getGraphics());}
});
Dynamic progress update of the progress bar is achieved via the below code:
int progress = Math.round(((float)finished/(float)(total)) * 100);
uploadPrgressBar.setIndeterminate(progress == 0);
uploadPrgressBar.setValue(progress);
uploadPrgressBar.update(uploadPrgressBar.getGraphics());
Call the method containing the above code in the loop(code logic) and it will dynamically update progress bar after each iteration