I have a class Pad_Draw extending JComponent. Constructor is
public Pad_Draw()
{
this.setDoubleBuffered(true);
this.setLayout(null);
};
The paintComponent methpod is :
public void paintComponent( Graphics g )
{
graphics2D = (Graphics2D)g;
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2D.setPaint(Color.white);
graphics2D.fillRect(0, 0, getSize().width, getSize().height);
}
In a JFrame I am adding this by a ScrollPane:
JScrollPane Padscroller = new JScrollPane();
Padscroller.setWheelScrollingEnabled(true);
Padscroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
Padscroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
Padscroller.setPreferredSize(new Dimension(200, 100));
Padscroller.setMinimumSize(new Dimension(200, 100));
Padscroller.setMaximumSize(new Dimension(200, 100));
Padscroller.setViewportView(drawPad);
content.add(Padscroller, BorderLayout.CENTER);
But as soon as I add the content in the Frame and set the size of the frame. The drawing pad is taking whole size whatever it needs.
I want my specified size (200,100) to be maintained and I actually want something like Windows Paint application has. I should be able to increase the size by extending a corner. As soon as I extend corner the scrollbar gets activated. Can anyone give me any idea how to achieve it?
The default layout manager for JFrame, BorderLayout does not respect preferred sizes of its components.
You could a layout manager that does, such as BoxLayout, and override getPreferredSize in your Padscroller component:
JScrollPane padScroller = new JScrollPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
};
Regarding increasing the size, have a look at using a MouseAdapter and updating this property in the mouseDragged method.
Related
I have a simple function that generates JFrame containing an image:
//The window
JFrame frame = new JFrame();
//Topmost component of the window
Container main = frame.getContentPane();
//Turns out this is probably the simplest way to render image on screen
//with guaranteed 1:1 aspect ratio
JPanel panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
//Put the image drawer in the topmost window component
main.add(panel);
//Set window size to the image size plus some padding dimensions
frame.setSize(image.getWidth(null)+1, image.getHeight(null)+15);
frame.setVisible(true);
Result:
I think this happens because the window dimensions include the size of the top bar and the window borders.
I also tried to set the size for JPanel and call pack() on JFrame:
//Set the size to the panel and let JFrame size itself properly
panel.setSize(image.getWidth(null), image.getHeight(null));
frame.pack();
Result is even worse:
So how can I precisely specify the inner window dimensions in pixels?
Here's the full function code.
Specify the preferred size of the panel by overriding the getPreferredSize method of JPanel and calling pack() on the JFrame before making it visible
JPanel panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(image.getWidth(), image.getHeight());
}
};
See the answers in Use of overriding getPreferredSize() instead of using setPreferredSize() for fixed size Components on the use and effect of either this technique, or the setPreferredSize method
I'm trying to draw shapes in a JPanel extending a JComponent and then putting the component inside the panel but it won't work. I've got a JFrame (500, 500) and I need the right half of it to have things drown inside. I'm clearly doing something wrong though!
This is the code I've used:
public class Componente extends JComponent{
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape linea = new Rectangle2D.Float(50, 50, 50, 50);
Shape cerchio = new Ellipse2D.Double(100, 100, 50, 50);
g2.setPaint(Color.BLUE);
g2.draw(linea);
g2.draw(cerchio);
}
}
public class PannelloDx extends JPanel{
PannelloDx(){
this.setBackground(Color.CYAN);
this.setSize(Esercitazione_Berni1703.finestra.getWidth()/2, Esercitazione_Berni1703.finestra.getHeight());
this.setLocation(Esercitazione_Berni1703.finestra.getWidth()/2, 0);
this.add(new Componente());
}
}
Now, the output shows the Cyan panel into the JFrame in the right half as it's supposed to. It won't show anything though!
By default a JPanel uses a FlowLayout and a FlowLayout respects the size of the component added to it. Your custom component has a preferred size of (0, 0) so there is nothing to paint.
You need to override the getPreferredSize() method of your custom panel to return the appropriate size.
Read the section from the Swing tutorial on Custom Painting for more information and examples. Check out the rest of the tutorial for Swing basics as well.
I have looked online, but I am still having trouble understanding how to add graphics to a JPanel
Here is the code for my panel class:
public class GamePanel extends JPanel {
public GamePanel(){
}
public void paintComponent(Graphics g) {
g.drawString("asd", 5, 5);
}
}
And my main method:
public static void main(String[] args) {
frame.setLayout(new FlowLayout());
frame.getContentPane().setBackground(Color.WHITE);
//i is an instance of GamePanel
frame.add(i);
frame.setPreferredSize(new Dimension(500, 500));
frame.pack();
frame.setVisible(true);
}
Text will only appear in a very tiny section of the screen (this applies to any graphics object I try to draw). What am I doing wrong?
FlowLayout respects preferred sizes of components. Therefore override getPreferredSize to give your JPanel a visible size rather than the default zero size Dimension that the panel currently has after JFrame#pack is called:
class GamePanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g); // added to paint child components
g.drawString("asd", 5, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 300);
}
}
Edit:
To eliminate gap between JPanel and its containing JFrame, set the vertical gap to 0:
frame.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
Two things jump out
Your Game panel has no preferred size, which, by default, makes 0x0. FlowLayout will use this information to make decisions about how best to layout your panel. Because the size is 0x0, the repaint manager will ignore it. Try overriding the getPreferredSize method and return a appropriate size or use a layout manager that does not use the preferred size, like BorderLayout
Your paintComponent method MUST call super.paintComponet
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 believe JViewport does work with JPanel, but when I build a new class that extends JPanel, it seem as if the JViewport is ignore by the program. I don't know if I do anything wrong, so this is the test I conduct and still get the same result:
public class panel extends JPanel
{
public panel()
{
super();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawString("Hello World", 50, 50);
g.setColor(Color.RED);
g.fillRect(50,50,100,100);
g.setColor(Color.BLACK);
g.fillOval(100, 100, 50, 50);
}
}
public class test extends JFrame
{
private panel p;
public void init()
{
this.setSize(1000, 1000);
this.setLayout(new BorderLayout());
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
p = new panel();
p.setOpaque(false);
JViewport v = new JViewport();
v.setViewSize(new Dimension(200,200));
v.setViewPosition(new Point(2000,2000));
v.setView(p);
this.add(v,BorderLayout.CENTER);
}
public test()
{
init();
}
public static void main(String[] args)
{
test t = new test();
}
}
It suppose to show part of the painted JPanel, but the JFrame window just display the whole JPanel. Therefore, I don't know if I did any wrong or JViewport is not built for this purpose. If it is the latter, then it would be great if anyone can suggest a workaround solution.
Thanks
The BorderLayout you're using is causing the viewport, which is placed in the center, to take the entire space inside the frame, since there are no other components in that layout. That's how the BorderLayout works.
Thus the viewport is also given a bigger size than defined (the size is overwritten by the layout manager). Since the panel doesn't have a fixed size either, it will also be resized.
In order to change that, either use a different layout manager or set a minimum/maximum size for the viewport and override getPreferredSize() for the panel.
As a side note: don't use lower case class names like panel.