How to do right packing of paintComponent in java? - java

1. Need set 1024*768 the size of paintComponent Area.
2. Need set drawing orientation of line on (0, 0, 1366,1024) but not a center.
I try to change the size in getPreferredSize() method but It's doesn't help me or doing another effect. I can't do this.
I try to change the size in getPreferredSize() method but It's doesn't help me or doing another effect.
I try to change
This is code which I can't change for my needs!
This is code which I can't change for my needs!
package j;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Letter {
LetterDraw letterDraw = new LetterDraw();
public Letter() {
JFrame frame = new JFrame();
JPanel letterDrawWrapper = new JPanel(new GridBagLayout());
letterDrawWrapper.add(letterDraw);
letterDrawWrapper.setSize(1024,760);
frame.add(createColorChooser(), BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setSize(111, 111);
frame.setVisible(true);
}
private JColorChooser createColorChooser() {
JColorChooser colorChooser = new JColorChooser();
colorChooser.getSelectionModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
letterDraw.setColor(colorChooser.getColor());
}
});
return colorChooser;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Letter();
}
});
}
}
class LetterDraw extends JPanel {
private Color color;
public void setColor(Color color) {
this.color = color;
repaint();
}
#Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g = (Graphics2D) graphics;
g.setColor(color);
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(new BasicStroke(3));
//g.setStroke(new BasicStroke(4, BasicStroke.JOIN_BEVEL, 0));
g.setColor(color);
g.drawLine(11,11,1024,1024);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
}```

Need set 1024*768 the size of paintComponent Area.
You should NOT be hard coding size values. You don't know what the resolution will be.
Also, The resolution of your screen is NOT the space available for painting. The frame has a title bar and border which takes away space for custom painting.
Painting code should be dynamic based on the space available to your panel, so the painting code would use methods like getWidth() and getHeight() to determine the painting area.
I try to change the size in getPreferredSize()
Yes that will work to give a suggestion for the preferred size. Then you just pack() the frame. Don't use setSize() on the frame.
//frame.setSize(111, 111);
That statement is overriding the size determined by the pack() method. Get rid of it.
g.drawLine(11,11,1024,1024);
Don't hard code values. The size of the panel will change as the frame is resized. For example to draw a diagonal line on the panel the code should be:
g.drawLine(0, 0, getWidth(), getHeight());
Try manually resizing the frame to see how the size of the line changes.
Edit:
You didn't add your panel to the frame:
frame.add(letterDraw);

Related

Why does the alpha in this timer draw on top of itself in this Java Swing Panel?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
frame.setSize(new Dimension(100, 100));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestPanel panel = new TestPanel();
panel.setPreferredSize(new Dimension(50,50));
frame.add(panel);
frame.setVisible(true);
}
static class TestPanel extends JPanel implements ActionListener{
private static final long serialVersionUID = 8518959671689548069L;
public TestPanel() {
super();
Timer t = new Timer(1000, this);
t.setRepeats(true);
t.start();
}
int opacity = 10;
#Override
public void actionPerformed(ActionEvent e) {
if(opacity >= 250) {
opacity = 0;
}
else {
this.setBackground(new Color(255, 212, 100, opacity));
this.repaint();
opacity+=10;
System.out.println("opacity is " + opacity);
}
}
}
}
The rate the alpha changes is faster than it should be. After it reaches a certain point, the opacity drops, while the the opacity printed in the console is less than 250. Resizing the window "resets" it, making the alpha correct.
How do I make it actually draw the alpha correctly?
this.setBackground(new Color(255, 212, 100, opacity));
Swing does not support semi transparent backgrounds.
Swing expects a component to be either:
opaque - which implies the component will repaint the entire background with an opaque color first before doing custom painting, or
fully transparent - in which case Swing will first paint the background of the first opaque parent component before doing custom painting.
The setOpaque(...) method is used to control the opaque property of a component.
In either case this makes sure any painting artifacts are removed and custom painting can be done properly.
If you want to use tranparency, then you need to do custom painting yourself to make sure the background is cleared.
The custom painting for the panel would be:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false); // background of parent will be painted first
Similar code would be required for every component that uses transparency.
Or, you can check out Background With Transparency for custom class that can be used on any component that will do the above work for you.

Drawing on a JPanel inside a JFrame using fillRect - rectangle sizing and position issues?

EDIT: Fixed up code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
public class JumpingBall extends JPanel{
#Override
public Dimension getPreferredSize()
{
return new Dimension(300,300);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D rectangle = (Graphics2D) g;
rectangle.setColor(Color.BLACK);
rectangle.fillRect(0,270,300,30);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Jumping Ball");
frame.getContentPane().add(new JumpingBall());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
}
I've set myself the task of writing some code that simple makes a ball jump from the floor at the users command. Step 1 was to create a window and a floor - I noticed that the location I added my floor tended to be off screen and discovered here that frame.setSize(x,y) includes the borders and you should embed a JPanel inside the frame and size that instead. However upon attempting to make these changes my rectangle.fillRect(x,y,width,height) seems to appear as a small square top center regardless of the variables. Why could this be happening?
Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
public class JumpingBall extends JPanel{
public void paint(Graphics g){
Graphics2D rectangle = (Graphics2D) g;
rectangle.setColor(Color.BLACK);
rectangle.fillRect(0,0,300,30);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Jumping Ball");
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(300,300));
panel.add(new JumpingBall());
frame.getContentPane().add(panel);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
}
Here's a screenshot of my failed floor.
When you do custom painting:
You should override paintComponent() not paint() and invoke super.paintComponent(g) as the first statement to make sure the background is cleared.
Override the getPreferredSize() method of the class to return the size of the panel so layout managers can do there job. So in your case it should be (300, 300).
In your code you should not be setting the preferred size of any components. It is the job of the layout manager to determine the preferred size of a component.
panel.setPreferredSize(new Dimension(300,300));
You currently set the preferred size of the panel holding the jumping ball. This doesn't help because the preferred size of the jumping ball has not been set. You see a (10, 10) square because the FlowLayout of the panel determines the preferred size of your jumping ball panel is only (10, 10).
Also, there is no need to create a separate panel. You can just add the JumpingBall panel directly to the frame.

Java JTabbedPane Inset Color

I was wondering how you would get the color of the inset of a JTabbedPane. I cannot seem to get this color. Every attempt I make I get 236,236,236 which is the outside frame color, where the inside frame color is about 10 darker, 227,227,227 (using the built in apple color meter).
I am setting the look and feel using UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
You can see this in an image that I found on the internet. http://pagesofinterest.net/wordpress/wp-content/uploads/2009/06/Quaqua-Maven-Netbeans.jpg Where the words "Panel's Title" is the area that I am getting the lighter color that is not useful to me. Inside the round corners is the darker color I am trying to obtain. I tried getting the color of the content pane to no avail.
Thanks for all your help!
**EDIT:**Added code! As you see, I am trying to get the color of the area inside the rounded corners(if your on a mac) not the color of the frame or the tabs that say "1" "2". I have attached a photo and I am trying to get the background color of the portion that says "Here" Thanks!
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
public class main {
JFrame frame;
Container c1 = new Container();
Container c2 = new Container();
JTabbedPane top = new JTabbedPane();
static main GUI;
public void createGUI(){
frame = new JFrame();
Container c = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
top = new JTabbedPane(JTabbedPane.TOP);
top.setFocusTraversalKeysEnabled(false);
top.setFocusable(false);
top.addTab("1", c1);
top.addTab("2", c2);
frame.setSize(315,450);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setResizable(true);
c.add(top);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {}
GUI = new main();
GUI.createGUI();
}
}
EDIT: camickr, Here is a screenshot of the UIManager Defaults. Unfortunately none of there colors in the are the correct color that the inset is.
You might be able to use UIMangaer Defaults to find the color.
You can override paintComponent() to use a GradientPaint in the tab's background, as shown below. A few notes,
Let the content adopt the preferred size of it contents, as shown here.
Construct the GUI in the event dispatch thread.
Use conventional Java names.
Addendum: the elements are not always in the same spot, so I do not know what place to get the color.
It sounds like you want to match a color used internally by the TabbedPaneUI delegate. One approach would be as follows:
Render a BufferedImage of the component, as shown here.
Determine the coordinates of a Point in top relative to the top of c1.
Point p = SwingUtilities.convertPoint(c1, 0, -1, top);
Obtain the color using getRGB(), as shown here; use Zoom to verify the result.
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
/** #see https://stackoverflow.com/a/16625260/230513 */
public class Main {
JFrame frame;
Container c1 = new GradientPanel();
Container c2 = new GradientPanel();
JTabbedPane top = new JTabbedPane();
private static class GradientPanel extends JPanel {
public GradientPanel() {
this.add(new JLabel("Here"));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
GradientPaint p = new GradientPaint(0, 0, Color.white,
getWidth(), getHeight(), Color.gray);
g2d.setPaint(p);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
public void createGUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
top = new JTabbedPane(JTabbedPane.TOP);
top.addTab("1", c1);
top.addTab("2", c2);
frame.add(top);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Main().createGUI();
}
});
}
}

Java - repaint(x, y, w, h) doesn't call paintComponent? (with SSCCE)

I asked this before, but only theoretically, without an SSCCE. Now, I've created one, and the problem persists. I'd like to know why paintComponent is not called on repaint(x, y, w, h), but is called on repaint().
Two classes:
SANDBOX
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class Sandbox {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setMinimumSize(new Dimension(800, 600));
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new FlowLayout());
// Add label
f.getContentPane().add(new TLabel());
f.setVisible(true);
}
}
and TLabel (with a little styling):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
#SuppressWarnings("serial")
public class TLabel extends JLabel {
public TLabel() {
super("TEST LABEL, NON-STATIC");
this.setHorizontalAlignment(SwingConstants.CENTER);
TLabel.this.setPreferredSize(new Dimension(200, 50));
TLabel.this.setMaximumSize(new Dimension(200, 50));
TLabel.this.setMinimumSize(new Dimension(200, 50));
TLabel.this.setOpaque(true);
TLabel.this.setBackground(Color.cyan.darker().darker());
TLabel.this.setForeground(Color.white);
TLabel.this.setBorder(new LineBorder(Color.orange, 2));
this.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
// EXPECTED BEHAVIOR HERE: This line will call paint and paintComponent.
//repaint();
// PROBLEM HERE: This line will not call paint or paintComponent.
repaint(TLabel.this.getBounds());
}
});
}
#Override
public void paint(Graphics g) {
// Note: This is called once when the label is realised.
// Note: This is called when the mouse enters the frame.
System.out.println("PAINT.");
super.paint(g);
}
#Override
public void paintComponent(Graphics g) {
// Note: This is called once when the label is realised.
// Note: This is called when the mouse enters the frame.
System.out.println("REPAINT.");
super.paintComponent(g);
}
}
You're calling this
repaint(TLabel.this.getBounds());
inside of the TLabel object. So repaint will try to paint a rectangle located relative to itself at the Bounds location, but getBounds() returns a rectangle located relative to this components containing object's location while repaint expects bounds relative to the component itself. So you're trying to paint a rectangle that has the width and height of your JLabel but which is located at x = 292 and y = 5 relative to the JLabel, when instead you want x and y to both be 0. In essence you're trying to draw way outside of this component.
Instead try this:
//!! repaint(TLabel.this.getBounds());
Dimension d = TLabel.this.getSize();
repaint(new Rectangle(0, 0, d.width, d.height));

How can I resize and paintComponent inside a frame

Write a program that fills the window with a larrge ellipse. The ellipse shoud touch the window boundaries, even if the window is resized.
I have the following code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,150,200);
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
And the main class:
import javax.swing.JFrame;
public class EllipseViewer {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(150, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
EllipseComponent component = new EllipseComponent();
frame.add(component);
frame.setVisible(true);
}
}
in your EllipseComponent you do:
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,getWidth(),getHeight());
I'd also recommend the changes given by Hovercraft Full Of Eels. In this simple case it might not be an issue but as the paintComponent method grows in complexity you realy want as little as possible to be computed in the paintComponent method.
Do not resize components within paintComponent. In fact, do not create objects or do any program logic within this method. The method needs to be lean, fast as possible, do drawing, and that's it. You must understand that you do not have complete control over when or even if this method is called, and you certainly don't want to add code to it unnecessarily that may slow it down.
You should create your ellipse in the class's constructor. To resize it according to the JComponent's size and on change of size, use a ComponentListener.:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
Ellipse2D ellipse = null;
public EllipseComponent {
ellipse = new Ellipse2D.Double(0,0,150,200);
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// set the size of your ellipse here
// based on the component's width and height
}
});
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
Caveat: code not run nor tested

Categories