How to fit the rectangle in the frame proportionally? - java

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.

Related

overriding JComponent methods

after running this code appears windows sized 0x0.
i can fix it by writting "f.setSize(640, 480);" in the main method.
i hear its bad pratice, so.. is there way to make this overriding work?
public class Gui {
public static void main(String[] args) throws IOException {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setBackground(Color.BLACK);
f.add(new DrawingPad());
f.setVisible(true);
}
}
class DrawingPad extends JComponent{
Image img = new ImageIcon("res/icon.jpg").getImage();
Dimension d = new Dimension(640, 480);
public void paintComponent(Graphics g){
g.drawImage(img, 50, 50, null);
}
#Override
public Dimension getPreferredSize(){return d;}
}
Call f.pack() before making the frame visible.
Quote from the javadoc:
Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. The resulting width and height of the window are automatically enlarged if either of dimensions is less than the minimum size as specified by the previous call to the setMinimumSize method.
Also, you should not use swing components from the main thread. Only from the event dispatch thread. Read http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html

Painting Grahpics2D Object on Frame with GridBagLayout

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();
}
});
}

Drawing from another class wont take the right dimensions of the JPanel

Ok i have a JPanel such as this one :
public class GUI {
JFrame frame = new JFrame("Net");
JPanel panel = new JPanel();
public GUI()
{
frame.setSize(835,650);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
frame.add(panel);
panel.setSize(600,600);
panel.setLocation(215,5);
panel.add(new DrawPlanes(300,300,200,Color.BLACK));}
There are some other panels in there tables etc. My main is this one :
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
//new GUI();
new GUI().buildTable();
}
});
And there i another class this one :
public class DrawPlanes extends JPanel
{
private static int centreX, centreY, radius;
private Color colour;
public DrawPlanes()
{
centreX = 300;
centreY = 300;
radius = 200;
colour = Color.BLACK;
}
public DrawPlanes(int centreX,int centreY, int radius, Color colour)
{
this.centreX = centreX;
this.centreY = centreY;
this.radius = radius;
this.colour = colour;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
System.out.println("ppp");
Graphics2D g2D = (Graphics2D) g;
g2D.setStroke(new BasicStroke(2F));
g.setColor(Color.BLACK);
g.drawOval(centreX - radius , centreY - radius, radius * 2 , radius * 2);
......
}
}
Ok so i ve setted the background colour of my panel red to see whats going on the whole panel its red but there is a small grey square where i believe the drawings are. I ve tried to change opaque as there might be an incompatibility issue but nothing changed at all.Any suggestions,is there anything that i m missing?
link of what is the result of
panel.add(new DrawPlanes(300,300,200,Color.BLACK))
http://dc626.4shared.com/img/FeYopZC1/s7/142d22f1be0/2013-12-08_142846.png?async&rand=0.9010817544924218
what does the DrawPlanes class draws when i checked it having the main and a panel etc in the DrawPlanes itself http://dc626.4shared.com/img/NPDkiQRJ/s7/142d22f23b0/1451491_586878858047235_191988.jpg?async&rand=0.27479583155781395 .When i apply a layout manager that grey square just moves to the center when i use getPreferredSize overriden or not the whole red panel appears grey.
frame.add(component) function eventually add your component to frame's content pane which has BorderLayout as default layout manager.
A JPanel uses FlowLayout as default layout which respect component's preferred size.
As your 'panel' and 'frame' is satisfying above two as a default, size hint with setSize(Dimension) or setBounds(Dimenstion) to component won't have effect.
You should provide size hint using setPreferredSize(Dimenstion)(to DrawPanel instance of your context) and if specifying minimum/maximum size is needed setMinimumSize(Dimenstion) and setMaximumSize(Dimenstion).
However it is considered as a better practice to override getXXXSize(Dimenstion): xxx represents Preferred/Minimmum/Maximum always which allows to adjust size of component with it's content.
Instead of calling setSize(Dimension) on a window it is preferable to call pack() at the end of addition of child components.
We should call setVisible(true) after finishing addition of all of the child components and following above point, after pack().
Please, start with the tutorial: Laying Out Components Within a Container
Edit:
Let us edit your GUI() constructor code and see what happens:
public GUI()
{
frame.setSize(835,650);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//frame.setVisible(true); // <<--- call it at the end of the code
frame.add(panel);
//panel.setSize(600,600); <<--- removing set size
panel.add(new DrawPlanes(300,300,200,Color.BLACK));
frame.setVisible(true);
}
And the DrawPnales will extend JComponent:
public class DrawPlanes extends JComponent{
public DrawPlanes(int centreX,int centreY, int radius, Color colour)
{
this.centreX = centreX;
this.centreY = centreY;
this.radius = radius;
this.colour = colour;
}
#Override
public Dimension getPreferredSize() {
return new Dimenstion(width, height);
// ^ provide your required size
}
}
If this still doesn't make any sense to you, then please try learning Swing layout managers a little bit further. Otherwise no matter how hard we hit our head on the table, possibly we won't be able to achieve any thing.
You're missing the fact that panels are laid out inside their container using a LayoutManager. The default layout manager of JPanel is a FlowLayout. The FlowLayout uses the preferred width and height of the components it lays out to decide where to place them in the container, and which size they should have. But your DrawPlanes panel doesn't override getPreferredSize(), so its preferred size is the default one.
Every time you use setSize() on a component or frame, you have a 99.9% probability of doing something wrong. Learn layout managers. If you design a custom component like your DrawPlanes component, which is not just a container for other components, but has a custom paintComponent() method, then override getPreferredSize(), getMaximumSize() and getMinimumSize() to tell the layout managers how they should display your component, and to make sure your custom component always has the appropriate size. You never set the size of a JButton, right? That's because the JButton itself decides, based on the text and icon it contains, which size it should have.

Having trouble adding graphics to JPanel

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

JViewport won't generate a viewport for JPanel's derived class

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.

Categories

Resources