Keeping track of strings drawn on JPanel using Paint in Swing - java

So, I have this simple program that paints a string on JPanel using g2.drawString("Hello world", 40, 120). Basically, I want to be able to keep track of many strings on the JPanel at once. I'm not sure how to do this. For example, I would want to have an ArrayList of objects that keep track of these strings.
I want to be able to click-and-drag these strings so I will need to know there locations, etc.
Right now, using g2.drawString, it only draws the string. I want something like gw.draw(myStringObject). Not sure if this is a dumb request but this is what I am looking for. Thanks!
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawSimpleText extends JPanel {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font font = new Font("Serif", Font.PLAIN, 96);
g2.setFont(font);
g2.drawString("Hello world", 40, 120);
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.getContentPane().add(new DrawSimpleText());
f.setSize(300, 200);
f.setVisible(true);
}
}

I want to be able to click-and-drag these strings so I will need to know there locations, etc.
Use a JLabel, then you can just drag them like any component.
See Component Mover for one way to do the dragging.

Related

BorderLayout only showing one object

I decided to write a small Java program to experiment around with BorderLayout, because I'm developing a Java game and I need to have 2 objects placed in a single JFrame at the same time, and everyone I asked said I need BorderLayout to do that.
So the Java program I wrote is supposed to place a JButton on the JFrame and ALSO place a graphic component (a rectangle in this case). The problem is, only the button shows up, as can be seen in the image link below:
http://prntscr.com/3m5ek6
I can't post actual images due to my low reputation statistic.
Here is the code:
main.java --> The main method class + JFrame/JPanel/JButton constructor
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class main {
public static void main(String[] args) {
Infout m = new Infout();
JFrame f = new JFrame();
JPanel start = new JPanel();
JPanel start2 = new JPanel();
start.add(m);
start2.add(new JButton("Hi"));
f.add(start,BorderLayout.LINE_START);
f.add(start2, BorderLayout.LINE_END);
f.setVisible(true);
f.setSize(300, 400);
}
}
Infout.java --> Rectangle constructor class
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
public class Infout extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Rectangle2D.Double(140, 270, 5, 300));
}
}
Can someone tell me what's wrong? Also, is using BorderLayout the best option for adding multiple static and/or dynamic objects to a JFrame?
Thanks!
Ab
You need to override the getPreferredSize() method so the layout manager can determine the proper size for the component.
How do I do that?
Read the section from the Swing tutorial on Custom Painting for more information on custom painting, including a working example that shows how to override the getPreferredSize() method.

Rectangle won't display in JFrame

So I've been trying for the last two hours to get this program to draw a simple rectangle in a frame but nothing gets displayed in the frame when i run the program. I've looked through textbooks and old notebooks and everything in my program seems to be fine, yet nothing is displayed. Help?
This is the class that creates the frame and is supposed to draw the rectangle.
import javax.swing.JFrame;
public class FrameViewer {
public static void main(String[] args) {
//creates an empty frame.
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("Empty Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//draws the rectangle within the frame.
RectangleComponent component = new RectangleComponent();
frame.add(component);
frame.setVisible(true);
}
}
And here is the RectangleComponent
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class RectangleComponent extends JComponent{
public void paintCOmponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Rectangle box = new Rectangle(5,10,20,30);
g2.draw(box);
}
}
Java is case sensitive, instead of
paintCOmponent
You want
paintComponent
You should use the #Override annotation to mark methods you think you are overriding as it will highlight problems like this.
The method should also remain protected, as there is no reason any one should be calling from outside the class
You may also want to take a look at Initial Threads

How do I make the JButtons all look the same when changing background color on some of them and not on others?

I have a JFrame that I am putting several JButtons on. Half the JButtons have color coding--i.e. I turn them blue when X event happens--and I use btn.setBackgroundColor(Color). When I use setBackgroundColor, I can see that I look the ones that are normal JButtons have shading/coloring/something that the ones with the setBackgroundColor do not. I've tried making the color transparent to a limited degree, but I still get a flat block of color, rather than a tinted version of the shaded button.
This seems like it should be a pretty easy thing to fix, but it is bugging me right now. I don't want to change the default LAF--it's fine. I don't want to abandon the color change. I do want the buttons to all appear styled (the word I'd use for HTML).
So I'm missing something right here....what is it?
Edited to add:
JFrame frame = new JFrame();
frame.add(new JButton("42"));
JButton btn24 = new JButton("24");
btn24.setBackground(Color.red);
frame.add(btn24);
frame.setVisible(true);
In the above example, "42" will--on my Windows machine--show a slight color variation at the bottom and the top, creating a rounded and shaded effect. The "24" button will show a red square. My question is: Is there a way to make "24" show the rounded/shaded/styled with the red tint on top? Or do I need to simple make all my buttons flat squares for a uniform appearance?
Thanks!
Create a custom JButton and override the paint method as illustrated bellow :
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
JButton btn24 = new DepthButton("24");
JButton btn25 = new DepthButton("25");
btn24.setBackground(Color.red);
btn25.setBackground(Color.GREEN);
JPanel pane = new JPanel(new BorderLayout());
pane.add(new JButton("42"), BorderLayout.PAGE_START);
pane.add(btn24, BorderLayout.PAGE_END);
pane.add(btn25, BorderLayout.CENTER);
frame.add(pane);
frame.pack();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
*
* #author Romain Guy
*/
public static class DepthButton extends JButton {
/** Creates a new instance of DepthButton */
public DepthButton(String text) {
super(text);
setContentAreaFilled(false);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
GradientPaint p;
p = new GradientPaint(0, 0, new Color(0xFFFFFF), 0, getHeight(), getBackground());
Paint oldPaint = g2.getPaint();
g2.setPaint(p);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setPaint(oldPaint);
super.paintComponent(g);
}
}
}
And Here is the Result:
The example is from an excellent book for advanced java swing : Filthy Rich Clients
https://github.com/romainguy/filthy-rich-clients/blob/master/Gradients/TwoStopsGradient/src/DepthButton.java

Draw string to image in Java

I need to draw a string to a BufferedImage in Java. The way this is done doesn't matter, however the image should take up only the space it needs, like in the example below.
I need a new BufferedImage created containing only the string. Extra space above the string and on the right side of the string could be tolerated, but I can't have extra space below and left of the drawn string.
Is something like this possible? I have tried to do it myself, but I always end up having extra space which is not what I want. Any help would be appreciated.
You can use Graphics2D#drawString method:
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass{
public static void main(String[] args) {
JFrame jf = new JFrame("Demo");
Container cp = jf.getContentPane();
MyCanvas tl = new MyCanvas();
cp.add(tl);
jf.setSize(300, 200);
jf.setVisible(true);
}
}
class MyCanvas extends JComponent {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font font = new Font("Serif", Font.PLAIN, 96);
g2.setFont(font);
g2.drawString("Test string", 40, 120);
}
}
I need to draw a string to an image in Java. I have tried to do it myself, but I always end up having extra space
I can't tell if you are trying to create an image of a String or add some text to an existing image. Since you say you have extra space I assume you are trying to create an image of the text and you don't know how big to make the BufferedImage that you are drawing on.
Create a JLabel with the text you want. Then you can use the Screen Image class to create an image of the label component. The the image will be the exact size pf the text.

Java - Graphics - Graphics object passed to paint() is different from Graphics object in JPanel instance

I have a JPanel that draws shapes and allows those shapes to be selected. I'm starting to add the capability to transform this view using the AffineTransform object, in conjunction with the Graphics2D object.
In my paint() method, of course a Graphics object is passed in. I set a new transform on that object (in this case, just scaling things by 2), and everything in the paint() method draws correctly according to the AffineTransform I just set. At this point the drawing shapes part works great! Now on to the shape selection...
Shape selection starts in the mousePressed() event (My JPanel implements the MouseListener interface). When I have a mousePressed() event, I call this.getGraphics() to get the JPanel's Graphics object. I then case it to a Graphics2D object and call getTransform() on it to get my current transform so I can map the clicked point to the transformed point. When I call getTransform(), however, the AffineTransform is back to the default AffineTransform of [1, 0, 0], [0, 1, 0].
I'm thinking that maybe the Graphics object passed to the JPanel's paint() is different than the one I have in my JPanel, but I'm not sure on that. Does anyone have any idea what's going on here?
Yes, you can't be sure that you will get the same Graphics object back. In fact, you shouldn't work with a Graphics object outside of the paintComponent() method, as this breaks the Swing UI model. You will probably get artifacts and/or incomplete drawing if you do this. The right approach is to have some instance variables that store the state of your UI/widget. When mousePressed() is called, you just update those variables and call repaint(). Then in your paintComponent() method, apply the appropriate transforms and draw your UI.
Simple Class Print An Object OR JPanel.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.DialogTypeSelection;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class TemplateDemo extends JFrame implements Printable, ActionListener {
JButton btn;
JTextField name_txt;
JPanel panel;
public TemplateDemo() {
panel = new JPanel(null);
panel.setBounds(0, 0, 300, 300);
add(panel);
name_txt = new JTextField();
name_txt.setBounds(0, 10, 200, 20);
panel.add(name_txt);
btn = new JButton("Click");
btn.setBounds(0, 240, 200, 30);
btn.addActionListener(this);
panel.add(btn);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0, 0, 400, 400);
setLayout(null);
setVisible(true);
}
#Override
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
Graphics2D graphics = (Graphics2D) g;
if (pageIndex == 0) {
g.translate((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY());
panel.print(g);
return PAGE_EXISTS;
}
return NO_SUCH_PAGE;
}
#Override
public void actionPerformed(ActionEvent e) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(this);
PrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
set.add(Chromaticity.COLOR);
set.add(DialogTypeSelection.COMMON);
if (pj.printDialog(set)) {
try {
pj.print(set);
} catch (PrinterException ex) {
}
}
}
public static void main(String[] args) {
new TemplateDemo();
}
}

Categories

Resources