So I have a JPanel that's inside a JScrollPane.
Now I am trying to paint something on the panel, but it's always in same spot.
I can scroll in all directions but it's not moving. Whatever I paint on the panel does not get scrolled.
I already tried:
A custom JViewPort
switching between Opaque = true and Opaque = false
Also I considered overriding the paintComponent method of the panel but that would be really hard to implement in my code.
public class ScrollPanePaint{
public ScrollPanePaint() {
JFrame frame = new JFrame();
final JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(1000, 1000));
//I tried both true and false
panel.setOpaque(false);
JScrollPane scrollPane = new JScrollPane(panel);
frame.add(scrollPane);
frame.setSize(200, 200);
frame.setVisible(true);
//To redraw the drawing constantly because that wat is happening in my code aswell because
//I am creating an animation by constantly move an image by a little
new Thread(new Runnable(){
public void run(){
Graphics g = panel.getGraphics();
g.setColor(Color.blue);
while(true){
g.fillRect(64, 64, 3 * 64, 3 * 64);
panel.repaint();
}
}
}).start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ScrollPanePaint();
}
});
}
}
The mistake I make is probably very easy to fix, but I just can't figure out how.
How to implement the paintComponent() on JPanel?
Override getPreferredSize() method instead of using setPreferredSize()
final JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
// your custom painting code here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(40, 40);
}
};
Some points:
Override JComponent#getPreferredSize() instead of using setPreferredSize()
Read more Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
Use Swing Timer instead of Java Timer that is more suitable for Swing application.
Read more How to Use Swing Timers
Set default look and feel using UIManager.setLookAndFeel()
Read more How to Set the Look and Feel
How to fix animation lags in Java?
I am trying to draw a coloured bar, which gets bigger as time goes on. It works when I use the default layoutmanager, but when im trying to implement this with GridBagLayout it wont. I wrote a test project just for testing purposes to investigate what the problem is. I added a few buttons just to have something else apart from the graphics2D object, so it kinda looks like my actual project im working on. But after a couple of days, i have to admit that i dont have a clue, what is going wrong. I hope someone can help me!
Just in advance, dont get confused by some words i used in the code. my mother tongue isn't english.
import java.awt.*;
import javax.swing.*;
import java.util.TimerTask;
import java.util.Timer;
public class FarbBalkenTest extends JPanel {
static Timer timer = new Timer ();
static TimerTask task ;
static int time;
public static void main(String[] args) {
FarbBalkenTest fbt = new FarbBalkenTest();
fbt.init();
}
public static void addComponent(Container cont, GridBagLayout gbl, Component c, int x, int y, int width, int height, double weightx, double weighty ){
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx=x;
gbc.gridy=y;
gbc.gridwidth=width;gbc.gridheight=height;
gbc.weightx=weightx;gbc.weighty=weighty;
gbl.setConstraints(c,gbc);
cont.add(c);
}
public void init (){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(new Color(230,230,230));
Container c = frame.getContentPane();
GridBagLayout gbl = new GridBagLayout();
c.setLayout(gbl);
ZeichenTest z_test = new ZeichenTest();
addComponent(c,gbl, new Button("top left"), 0,0,1,1,1.0,1.0);
addComponent(c,gbl, new Button("top right"), 2,0, 1,1,1.0,1.0);
addComponent(c, gbl,z_test, 1,1,1,1,1.0,1.0);
addComponent(c,gbl, new Button("down left"),0,2,1,1,1.0,1.0);
addComponent(c,gbl, new Button("down right"),2,2,1,1,1.0,1.0);
frame.setSize(500,500);
frame.setVisible(true);
task = new TimerTask(){
public void run(){
frame.repaint();
time+= 20;
System.out.println(time);
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}
public class ZeichenTest extends JComponent {
public void paintComponent (Graphics g){
Graphics2D g2d = (Graphics2D) g;
Color startgreen = new Color(50,205,50);
Color endred = new Color (255, 97, 3);
GradientPaint startend = new GradientPaint(0,25 , startgreen, 400, 25 , endred );
g2d.setPaint (startend);
g2d.fillRect(50, 200 , time, 50);
}
}
}
"It works when I use the default layoutmanager, but when im trying to implement this with GridBagLayout it wont."
GBL respects preferred sizes. Your ZeichenTest has none. You need to explicitly set it by overriding getPreferredSize(). (The default layout of JFrame which is BorderLayout doesn't respect preferred sizes, and will stretch you panel to fit)
public class ZeichenTest extends JComponent {
...
#Override
public Dimension getPreferredSize() {
return new Dimension( ... , ... );
}
}
Also note, after setting the preferred size of the component, just call pack() on the frame, instead of setSize(). The pack() will "fit" everything according to the preferred sizes. You can actually test that your component currently has no preferred size by calling pack() instead of setSize() and you will see the frame shrink on launching. But if you override the getPreferredSize() of the component and call pack, the frame will be size according the new preferred size.
Other Important notes:
Use java.swing.Timer instead of TimerTask. repaints should be done on the EDT and Swing Timer handles this for you. See more at How to Use Swing Timer
I think you mean to repaint() the instance of ZeichenTest and not the frame. It makes a difference.
Always call super.paintComponent in your paintComponent method, as to not leave nasty paint atrifacts
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
Swing apps should always be run on the Event Dispatch Thread (EDT). See Initial Threads. Basically, in this case, just wrap the main code in a SwingUtilities.invokeLater(...)
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
FarbBalkenTest fbt = new FarbBalkenTest();
fbt.init();
}
});
}
I've been coding a simulation for a traffic flow network in Java, and the class that is supposed to graphically model the network looks as follows:
public class Map extends JPanel {
BufferedImage truck1;
public Map() throws IOException{
truck1 = ImageIO.read(getClass().getResource("Truck.png"));
}
protected void paintcomponent (Graphics g) {
super.paintComponent(g);
g.drawImage(truck1, 50, 100, 300, 300, this);
}
}
In my main() function, I instance the object as follows at the very beginning of the function:
Frame F1 = new Frame();
F1.setLayout(new FlowLayout());
F1.setSize(500,500);
F1.setVisible(true);
Map map = new Map();
map.setOpaque(true);
F1.add(map);
F1.setVisible(true);
However, when I run the program, the only output is a blank window with a slightly darker grey small square exactly in the middle at the top of the window. I've added Truck.png to the project, and I can't see any reason why it shouldn't display properly. What am I doing wrong?
Components should be added to the frame before the frame is made visible.
You are using a FlowLayout for your frame. A FlowLayout respects the preferred size of all components. Your Map class doesn't have a preferred size so the size defaults to (0, 0) so there is nothing to paint. Override the getPreferredSize() method of the Map class to return the appropriate size for the component.
Try to draw a rectangle with different size, How to fit it in one frame proportionally(assume the frame is fixed)?
public class Draw extends JComponent {
public void paint(Graphics g) {
int width = 100;
int length = 100;
g.drawRect(10, 10, width, length);
}
}
public class DrawRect {
public static void main(String[] a) {
JFrame frame = new JFrame();
frame.setSize(400, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Container content = frame.getContentPane();
content.add(new Draw());
}
}
Custom painting is done by overriding the paintComponent(...) method, not the paint() method. This advice is made daily. Search the forum for more information and examples.
If you want to know the space available to the component then you can invoke the getWidth() and getHeight() method. Once you know these values you can determine how big you want to paint your rectangle.
Components should be added to the frame BEFORE the frame is made visible.
You don't need to use the getContentPane() method. Since JDK5 you can just add components directly to the frame and they will be added to the content pane for you.
I am completely new to netbean's graphics system, and have been struggling with a java textbook. I am trying to produce a simple program to display some things, and have followed the book exactly as it wants me to. I found in my research a bunch of other people with a similar issues. These people tend to be told to use dimensions and preferredSize methods, though neither of these are mentioned in the section of the book I am trying to reproduce in java. The following is my code:
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame frame = new JFrame(); //create frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //makes x button end program
frame.setSize(300,200); //determine the size of the frame
ImageIcon image = new ImageIcon("panda.jpg");
ColorPanel p = new ColorPanel(Color.pink, image);
Container pane = frame.getContentPane();
pane.add(p);
frame.setVisible(true); //make frame show up
}
}
public class ColorPanel extends JPanel {
ImageIcon image;
public ColorPanel(Color c, ImageIcon i){
setBackground(c);
image = i;
}
#Override
public void paintComponents(Graphics g){
super.paintComponents(g);
setPreferredSize(new Dimension(100,100));
System.out.println("Blah!");
g.setColor(Color.blue);
g.drawRect(10,25,40,30);
}
}
I suppose there is a small typo in your code. You definitely mean to override paintComponent() and not paintComponents(). The first is called to paint the component, the second one to paint all components contained in your panel. Since there is none it will not be called.
These people tend to be told to use dimensions and preferredSize methods
You should not really use setPreferredSize(). Instead, you should override the getPreferredSize() method to return a proper value.
Also, you should never invoke setPreferredSize() in the paintComponent() method or change any property of the class in the paintComponent() method.