Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
say at first rectangle and then a line for example
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Canvas;
import javax.swing.JComponent;
import javax.swing.JFrame;
//class MyCanvas extends JComponent {
class MyCanvas extends Canvas {
public void paint(Graphics g) {
g.fillRect(20, 20, 500, 500);
}
}
class Linie extends MyCanvas {
public void paint(Graphics g) {
g.setColor(new Color(0, 255, 0));
g.drawLine(30, 40, 300, 100);
}
}
public class LinieUndRec {
public static void main(String[] a) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(100, 100, 800, 800);
window.getContentPane().add(new MyCanvas());
window.getContentPane().add(new Linie());
window.setVisible(true);
}
}
this code draws only a line
how to draw a rectangle and a line
In your implementation of the Linie class, you're providing code for the paint method. This replaces the code of the paint method on the MyCanvas class, because Linie extends MyCanvas.
So, when you call paint() on an instance of Linie only the code in the Linie.paint() method is run, not both. If you want it to run both, add do this:
class Linie extends MyCanvas {
public void paint(Graphics g) {
super.paint(g); // This will draw the rectangle from the parent class,
// then render the line below
g.setColor(new Color(0,255,0));
g.drawLine(30,40, 300, 100);
}
}
As a side note, even though the code above should work, type inheritance isn't meant to solve this kind of problem. I'm just trying to provide an answer to the code as provided.
If you really want to draw a rectangle followed by a line, then call .paint() on an object that represents a rectangle, then call .paint() on an object that represents a line, one after the other. What you have here is...well, really bad code (that's okay if you're new to Java - we were all new once). You're using inheritance to accomplish what would be done by just calling two .paint() commands after each other.
Also as #Durandal points out, you can use a single canvas to do all drawings. You don't need one canvas per drawing operation. Think of a Canvas as a surface you can draw on, like a piece of paper or, well, like a painter's canvas. And think of the drawing operations as instructions of what to do in order to construct a painting. Generally speaking, you must draw things in the background first, followed by things in the foreground. The result is that drawing that happens first is covered up by drawing that happens later.
Related
This question already has answers here:
drawing simple rectangles on a Jframe in java
(3 answers)
Closed 6 years ago.
I am trying to draw a rectangle in my JFrame but when I run it it just comes up blank. I have tried a few other ways to draw it, but they all come up the same. Keep in mind I'm pretty new, so I'm sorry if there are any obvious mistakes :P.
import javax.swing.*;
import java.awt.*;
public class Main {
JFrame jf1;
public Main() {
jf1 = new JFrame("Draw");
jf1.setVisible(true);
jf1.setSize(900, 700);
jf1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
jf1.setLocation(dim.width/2-jf1.getSize().width/2, dim.height/2-jf1.getSize().height/2);
}
public void paint(Graphics g) {
g.fillRect(0, 60, 100, 50);
g.setColor(Color.BLACK);
}
public static void main(String[] args) {
Main shoe = new Main();
}
}
Your class has a paint method but it's meaningless since the class extends no GUI component and the method is not a true painting method override. Rather than guess at this stuff, read the graphics tutorials:
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
Then create a class that extends JPanel and draw in its paintComponent method as the tutorials will show you. Place your JPanel in a JFrame and you should be good.
Also -- remember to append #Override before any method that you think should override a super class's method. If you had done this, the compiler would have complained that your paint method is not in fact overriding anything. Also, don't forget to call the super's paintComponent method as well explained in the first tutorial.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I am new to java and I want to draw circle and rectangle by using java code. I did write code for that purpose and tried at my own. But on Panel is appearing and shapes are not appearing.
Code of "MyPanel" is given below
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel{
public void painComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.drawRect(20,20,20,20);
g2.setColor(Color.blue);
g2.fillOval(50,20,20,20);
g2.drawString("Hello World", 120, 50);
}//end painComponent
}//end test class
Cdoe of driver class "Test" is given below.
import javax.swing.*;
import java.awt.*;
public class Test{
JFrame f;
MyPanel p;
public Test(){
f = new JFrame();
Container c = f.getContentPane();
c.setLayout(new BorderLayout());
p = new MyPanel();
c.add(p, BorderLayout.CENTER);
f.setSize(400,400);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}//end of constructor
public static void main(String args[]){
Test t = new Test();
}
}
And as per my knowledge when frame becomes visible through the paintChildren() method then panel should become visible
Also to become visible panel will call paintComponent() method which will do your custom drawing, but it seems like panel is not calling paintComponent().
Your method in MyPanel is called painComponent :-).
That is why the method from the base class is called, your method does not override any method from JPanel.
You are doing some spelling mistake. Method inside “MyPanel” is painComponent() rather paintComponent()
“t” is missing from your prototype that is why your program was not able to override paintComponent() in MyPanel class.
So all you have to do is that just update your code and replace with “paintComponent();”
Complete class code is given below,
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.drawRect(20,20,20,20);
g2.setColor(Color.blue);
g2.fillOval(50,20,20,20);
g2.drawString("Hello World", 120, 50);
}//end painComponent
}//end test class
I have tested this code it works fine.
In MyPanel class, the method name should be paint, instead of painComponent.
It is an overridden method, hence, the name matters.
Please change the name of the method to "paint" and try.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've looked around a little, and I was surprised that I couldn't find a way to draw and fill a parallelogram with java swing. Is there a easy way to do that?
Thanks for your help in advance.
All (or at least most) drawing in swing is done by subclassing JPanel and overriding the paintComponent method. So it will start like this:
public class MyPanel extends JPanel{
#Override
public void paintComponent(Graphics g){
//Drawing stuff....
}
}
From here, you're going to want to create a Parallelogram Shape, and fill it. The simplest implementation of Shape for your use is Path2D.
public class MyPanel extends JPanel{
private Path2D.Double parallelogram;
public MyPanel(){
parallelogram = new Path2D.Double();
parallelogram.moveTo(0,0);
parallelogram.lineTo(50,0);
parallelogram.lineTo(100,50);
parallelogram.lineTo(50,50);
parallelogram.closePath();
setPreferredSize(new Dimension(100, 100));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.BLACK);
g2d.fill(parallelogram);
}
}
Then create an instance of this panel and add it to a JFrame:
public static void main(String[] args){
JFrame f = new JFrame();
f.add(new MyPanel(), BorderLayout.CENTER);
f.pack();
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Suggestions:
Create a Shape using a Path2D object,
start your parallelogram using its moveTo(...) method
Continue drawing lines using its lineTo(...) methods.
Draw in the paintComponent(Graphics g) method override of a JPanel.
In this method cast the Graphics object into a Graphics2D object.
Then call fill(yourShape) passing in your Path2D object.
I want my program to display the canvas that is repainted once at the start and then whenever a change is made afterwards. I thought I had everything coded correctly, but for some reason nothing that is painted onto the canvas actually shows (I know it's repainting, I tested that).
Here are the code segments:
public TileMapCreator()
{
currentView = new BufferedImage(640, 640, BufferedImage.TYPE_INT_ARGB);
currentView.getGraphics().setFont(new Font("Arial", Font.BOLD, 100));
currentView.getGraphics().drawString("No Map Yet Open", currentView.getWidth()/2, currentView.getHeight()/2);
this.setJMenuBar(createMenuBar());
this.setContentPane(createMapPanel());
}
private JPanel createMapPanel()
{
JPanel p = new JPanel();
p.add(setUpCanvas());
p.setVisible(true);
return p;
}
private Canvas setUpCanvas()
{
mapCanvas = new Canvas(){
private static final long serialVersionUID = 1L;
public void repaint()
{
mapCanvas.getGraphics().drawImage(currentView, 0, 0, this);
}
};
mapCanvas.setIgnoreRepaint(true);
Dimension size = new Dimension(currentView.getWidth(), currentView.getHeight());
mapCanvas.setSize(size);
mapCanvas.setPreferredSize(size);
mapCanvas.setMaximumSize(size);
mapCanvas.setMinimumSize(size);
mapCanvas.setFocusable(true);
mapCanvas.addMouseListener(this);
mapCanvas.addMouseMotionListener(this);
mapCanvas.setVisible(true);
return mapCanvas;
}
Currently the area where the canvas should be painting is just the regular grey color of the Java GUI. Thanks for your help!
You appear to be mixing Swing with AWT components, and drawing in a very strange way, one that I've honestly never seen before (and I've seen a lot). Why not simply do your drawings in the paintComponent(Graphics g) method of a JPanel using the Graphics object given by the JVM, like you'll find in the Swing graphics tutorials and 98% of the Swing graphics answers on this site? Also for my money, I'd avoid using Canvas or trying to mix heavy and light weight components together. Stick with Swing all the way, and things should go more smoothly.
I'd be happy to give you more specific advice and perhaps some if you could create and post a minimal example program. Please have a look at the link and let us know if you need more information.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestImagePanel extends JPanel {
private static final int BI_WIDTH = 640;
BufferedImage currentView = new BufferedImage(BI_WIDTH, BI_WIDTH, BufferedImage.TYPE_INT_ARGB);
public TestImagePanel() {
Graphics g = currentView.getGraphics();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setColor(Color.black);
g.setFont(new Font("Arial", Font.BOLD, 60));
g.drawString("No Map Yet Open", 20, currentView.getHeight()/2);
g.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (currentView != null) {
g.drawImage(currentView, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (currentView != null) {
return new Dimension(BI_WIDTH, BI_WIDTH);
}
return super.getPreferredSize();
}
private static void createAndShowGui() {
TestImagePanel mainPanel = new TestImagePanel();
JFrame frame = new JFrame("TestImagePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I've found the Swing tutorials to be a great asset, and bet you would too. Please have a look at them.
Edit
You ask:
Hmm, so apparently getting the graphics object of my buffered image twice did not result in anything actually being painted... I had to get the graphics object, assign it to a variable, and then paint.
I wouldn't say that. I'd say that your way of getting the Graphics object should work the same as mine, but yours is not safe since the Graphics objects obtained in this way cannot be disposed of, and you risk running out of resources. I think that your image didn't show up due to your very convoluted and unusual way of trying to display your image. You override repaint(), put some weird code inside of it, tell the JVM to ignore repaint calls, never call the repaint super method inside of your override, so that repaint does in fact nothing. I have to wonder -- where did you get this code? Was it from a tutorial? If so, please share the link here. And never get advice from that site again.
I've got a JButton which is painted using a custom UI delegate (CustomButtonUI extends BasicButtonUI). The CustomButtonUI's paint() method draws the button with rounded "antialiased" corners, to make the apperance as "smooth" as possible.
Somehow the "antialiased" edges of the button disappears each time i drag the mouse over the
button. This makes the button edges look "pixelized". However, once I add a line of code to repaint the parent of the button, the antialiasing kicks in even when i drag the mouse over the button.
Now, my question relates to wether this is a good idea? I do after all repaint the parent component from a child component. I wonder if this lead to a loop of repaints? If the parent
tries to repaint its children and the children tries to repaint its parent - then i assume we're talking about a loop.
I've attached my code as a reference. Any comments are very welcome!
public class JCustomButtonUI extends BasicButtonUI {
#Override
public void installUI(JComponent c) {
super.installUI(c);
AbstractButton b = (AbstractButton) c;
b.setBorderPainted(false);
}
#Override
public void paint(Graphics g, JComponent c) {
//Cast the Graphics instance to a Graphics2D instance.
Graphics2D g2d = (Graphics2D) g;
JButton b = (JButton) c;
//Repaint parent component to make sure that we get "antialiased"
//edges.
b.getParent().repaint();
//Get the component's height and width.
int w = (int) g.getClipBounds().getWidth();
int h = ((int) g.getClipBounds().getHeight());
//Make sure the button is drawn with "antialiased" edges.
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GRAY);
g2d.fillRoundRect(0, 0, w, h, w, h);
}
}
Update 1
Just to illustrate the alias and antialiased border, please have a look at the below two pictures. When i (from the ButtonUI's paint() method) manually invoke the parent JPanel's repaint method, all borders are perfectly antialiased all the time. However, when i do not manually invoke the parent JPanel's repaint method, then the borders are no longer antialiased once i hoover the mouse over the button.
Update 2
I have shared the entire "component" which consists of a JPanel, a JSlider and a couple of JButtons on Snipt. Please get it from http://snipt.org/wnllg.
Update 3
It seems that i have managed to get it working. Instead of painting the JPanel's background in its paintComponent() method, i created a JCustomPanelUI which i installed on the JPanel. I don't think that was the solution itself, but instead of using width and height from the Graphics instance, I tried using widht and height from the JPanel itself. I'm not quite sure why things go wrong when i use width and height from the Graphics instance. I thought the width and height from the Graphics instance was already "prepared" with regard to dimensions from the JPanel component. You can have a look at the final component here: http://snipt.org/wnlli,
I've reduced the example to just the anti-aliasing, and I am unable to reproduce the problem. It doesn't appear to be platform dependent. I'm not sure why you are using getClipBounds().
Addendum:
The JPanel background (a gradient) needs to shine through…
I've update the example to use a gradient background behind a transparent button; I've put anti-aliased (left) and aliased (right) examples side-by-side. I see no unexpected behavior.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicButtonUI;
/** #see http://stackoverflow.com/questions/5169647 */
public class ButtonUITest extends JPanel {
public ButtonUITest() {
this.setLayout(new GridLayout(1, 0));
this.setPreferredSize(new Dimension(640, 480));
this.add(new CustomButton(true));
this.add(new CustomButton(false));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = this.getWidth();
int h = this.getHeight();
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(new GradientPaint(0, 0, Color.blue, w, h, Color.red));
g2d.fillRect(0, 0, w, h);
}
private void display() {
JFrame f = new JFrame("ButtonUITest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static class CustomButton extends JButton {
public CustomButton(boolean antialiased) {
this.setOpaque(false);
this.setUI(new CustomButtonUI(antialiased));
}
}
private static class CustomButtonUI extends BasicButtonUI {
private boolean antialiased;
public CustomButtonUI(boolean antialiased) {
this.antialiased = antialiased;
}
#Override
public void paint(Graphics g, JComponent c) {
int w = c.getWidth();
int h = c.getHeight();
Graphics2D g2d = (Graphics2D) g;
if (antialiased) {
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillOval(0, 0, w, 2 * h);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ButtonUITest().display();
}
});
}
}
For antialiasing to work consistently, your component needs to return false for isOpaque. Otherwise, the RepaintManager is free to skip painting the region behind your component.
I suspect that if you use a screen magnifier to look at the "unaliased" edges, you will find they really are antialiased. But it was done against against a black, unpainted background, not the parent's background.
The Swing experts who know what they're talking about will be here shortly. In the meantime, let me comment on this:
Now, my question relates to wether
this is a good idea? I do after all
repaint the parent component from a
child component. I wonder if this lead
to a loop of repaints? If the parent
tries to repaint its children and the
children tries to repaint its parent -
then i assume we're talking about a
loop.
Once you try it out and see that it's not a problem on your machine, chances are that it will be true on all JVMs you try. That is to say, the proof is in the pudding, or random bumbling does generally lead to positive results in Swing. Recursive loops have a way of causing the program to halt pretty quickly in Java, so the answer is... if this were totally wrong you'd already know. Plus you can put sysouts in there to see if this is happening (it's obviously not).
That said, there may be a better way to deal with your problem, but if your answer works, stick with it for now.
AFAIK, repaint() just tells the system to repaint that component in the next paint cycle, i.e.
if you call repaint() in a paint() method the repaint might be done in the next cycle.
Generally, Swing runs in its own thread, so repeated repaint should not stop the application logic. However, it might be using processing power, if the system always repaints the ui even if there are no changes.
You could try and write a log message to see when and how often the button is painted.
If that happens continously even if nothing happens that would cause a ui update, you might have to find a solution. If not, you should be fine.
Edit: there is a class called RepaintManager that you might find interesting.
Doing a repaint in there is definitely a bad idea. Try adding b.setOpaque(false) in installUI(). Your button is no longer painting its entire bounds because of the antialiasing. You need to let the background show through to fill the gaps.