Related
I'm trying to write a function that will draw the pictured smiley face
I need to pass in parameters for location and size of the smiley face. For example, if the location passed in was (0,0) and size 100, then the yellow circle would be a width and height of 100, the eyes are black circles located at (30,30) and (60,30) with a width and height of 5, and the mouth is a black semi-circle inset by 10 pixels. Lastly I need to call the smiley function from paintComponent then use it as a stamp to draw at least 5 different smileys in different locations and sizes.
I know I need to create a equation that will do all of this but am unaware as to how to accomplish this because when I change the x and y coordinates the eyes of the smiley face are not in the proper position as they were before the change. anything helps, thanks.
public class GuiApp extends JFrame
{
private DrawingPanel panel;
public class DrawingPanel extends JPanel
{
public DrawingPanel()
{
this.setBackground(Color.RED);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// drawFlower(g, 20, 10, 10);
drawSmiley(g, 25, 25, 100);
}
}
public GuiApp()
{
setBounds(100, 100, 450, 300);//x,y,w,h of window
panel = new DrawingPanel();
this.setContentPane(panel);
}
public static void main(String [] args)
{
GuiApp f = new GuiApp();
f.setTitle("Smiley");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public void drawFlower(Graphics g,int x,int y,int s)
{
g.drawOval(60, 60, 200, 200);
g.fillOval(90, 120, 50, 20);
g.fillOval(190, 120, 50, 20);
g.drawArc(110, 130, 95, 95, 0, -180);
}
public void drawSmiley(Graphics g, int x, int y, int s)
{
g.setColor((Color.YELLOW));
g.fillOval(x-s/2, y-s/2, s, s);
g.setColor((Color.blue));
g.fillOval((int)(1+(x-s/2)+(x-s/2)*.3), (int)(1+(y-s/2)+(y-s/2)*.3),(int)(s*.10),(int)(s*.10));
g.fillOval((int)(1+(x-s/2)+(x-s/2)*.9), (int)(1+(y-s/2)+(y-s/2)*.3),(int)(s*.10),(int)(s*.10));
g.drawArc((int)(1+(x-s/2)+(x-s/2)*.1), (int)(1+(y-s/2)-(y-s/2)*.15), (int)(s*.9), (int)(s), 0, -180);
}
}
Remember, most graphical operations occur from the top/left corner, so when drawing something like an oval, the x/y is the top/left corner of the oval and it will expand right/down.
So, this means that when drawing the right eye, for example, you will not only need to calculate the x/y position as a factor of the diameter of the circle, but you may need to subtract the width of the eye itself from the horizontal to make it "look" right
Now, you can make your life easier by using Graphics#translate to move the origin/starting point of all graphical operations to that new location, this will reduce the amount of calculations you need to make. This also means that you could, technically, write two methods, one which did the actual painting of the smiley face starting from position 0x0 and one which translated the position (based on the parameters) and then called the first, but that's just an example idea ;)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Smile {
public static void main(String[] args) {
new Smile();
}
public Smile() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawSmiley(g, 25, 25, 100);
}
public void drawSmiley(Graphics g, int x, int y, int s) {
Graphics copy = g.create();
copy.translate(x, y);
copy.setColor((Color.YELLOW));
copy.fillOval(0, 0, s, s);
copy.setColor((Color.blue));
copy.fillOval((int) (1 + s * .3), (int) (1 + s * .3), (int) (s * .10), (int) (s * .10));
copy.fillOval((int) ((1 + s * .7) - (s * .10)), (int) (1 + s * .3), (int) (s * .10), (int) (s * .10));
double width = s * 0.8;
double height = s * 0.8;
copy.drawArc((int)((s - width) / 2d), (int)((s - height) / 2d), (int)width, (int)height, 0, -180);
copy.dispose();
}
}
}
package guimodule;
import processing.core.PApplet;
public class MyDisplay extends PApplet {
public void setup() {
size(400, 400);
background(200, 200, 200);
}
public void draw() {
fill(255, 255, 0);
ellipse(200, 200, 390, 390);
fill(0, 0, 0);
ellipse(120, 130, 50, 70);
ellipse(280, 130, 50, 70);
noFill();
fill(0, 0, 0);
arc(200, 280, 145, 120, 0, PI);
}
}
I am making a GUI that has Graphics2D objects drawn on a JPanel within a JFrame. When I resize the window the Graphics2D objects reduce into a tiny rectangle. How can I set the drawing to resize with the JFrame when the user resizes the window?
I have tried using gridlayout, flowlayout, borderlayout, and settled on gridbaglayout. This helps with the resizing of btnPanel and the JButton but not for the Graphics2D objects.
Here is my self contained example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class DrawPanelMain extends JPanel {
/*
* Variables used to set the value of preferred height and width
*/
public static final double version = 0.0;
JPanel btnPanel = new JPanel();
JPanel switchPanel = new JPanel();
DrawEllipses drawEllipses = new DrawEllipses(POINT_LIST);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initializePointList();
createAndShowGui();
}
});
}
public static java.util.List<Point> POINT_LIST = new ArrayList<>();
/*
* This loop will initialize POINT_LIST with the set of points for drawing the ellipses.
* The for each loop initializes points for the top row and the second for loop draws the
* right triangle.
*/
public static void initializePointList() {
int ellipsePointsYCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620};
int ellipsePointsXCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620, 680};
int xx = 80;
for (int aXt : ellipsePointsXCoordinate) {
POINT_LIST.add(new Point(aXt, xx));
}
for (int i = 0; i < ellipsePointsYCoordinate.length; i++) {
for (int j = i; j < ellipsePointsYCoordinate.length; j++) {
POINT_LIST.add(new Point(ellipsePointsXCoordinate[i], ellipsePointsYCoordinate[j]));
}
}
}
public DrawPanelMain() {
switchPanel.setBorder(BorderFactory.createLoweredSoftBevelBorder());
switchPanel.setBackground(Color.DARK_GRAY);
switchPanel.add(drawEllipses);
switchPanel.revalidate();
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
// first column
c.gridx = 0;
add(switchPanel, c);
// second column
c.gridx = 1;
add(switchPanel, c);
// first row
c.gridy = 0;
// second row
c. gridy = 1;
add(btnPanel, c);
btnPanel.add(new JButton(new AddSwitchAction("Add Switch Panel")));
}
public static void createAndShowGui() {
JFrame frame = new JFrame("RF Connection Panel " + version);
frame.setLayout(new BorderLayout());
frame.add(new DrawPanelMain());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(false);
//frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
/*
* AddSwitchAction will add a new pane to the tabbedPane when the add switch button is clicked
*/
private class AddSwitchAction extends AbstractAction {
public AddSwitchAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
String title = "Switch ";
DrawEllipses tabComponent = new DrawEllipses(POINT_LIST);
switchPanel.add(title, tabComponent);
}
}
}
#SuppressWarnings("serial")
class DrawEllipses extends JPanel {
private final int PREF_W = 750; //Window width
private final int PREF_H = 750; //Window height
private final int OVAL_WIDTH = 30;
private static final Color INACTIVE_COLOR = Color.RED;
private static final Color ACTIVE_COLOR = Color.green;
private java.util.List<Point> points;
private java.util.List<Ellipse2D> ellipses = new ArrayList<>();
private Map<Ellipse2D, Color> ellipseColorMap = new HashMap<>();
/*
* This method is used to populate "ellipses" with the initialized ellipse2D dimensions
*/
public DrawEllipses(java.util.List<Point> points) {
this.points = points;
for (Point p : points) {
int x = p.x - OVAL_WIDTH / 2;
int y = p.y - OVAL_WIDTH / 2;
int w = OVAL_WIDTH;
int h = OVAL_WIDTH;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
ellipses.add(ellipse);
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
MyMouseAdapter mListener = new MyMouseAdapter();
addMouseListener(mListener);
addMouseMotionListener(mListener);
}
/*
* paintComponent is used to paint the ellipses
*/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2.setColor(ellipseColorMap.get(ellipse));
g2.fill(ellipse);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
}
/*
* Set the font characteristics, color, and draw the row labels.
*/
g.setFont(new Font("TimesRoman", Font.BOLD, 18));
g.setColor(Color.BLACK);
//Along the top row
g.drawString("External Port", 10, 50);
g.drawString("1", 135, 50);
g.drawString("2", 195, 50);
g.drawString("3", 255, 50);
g.drawString("4", 315, 50);
g.drawString("5", 375, 50);
g.drawString("6", 435, 50);
g.drawString("7", 495, 50);
g.drawString("8", 555, 50);
g.drawString("9", 615, 50);
g.drawString("10", 672, 50);
//Along the Y-axis
g.drawString("Radio 2", 40, 145);
g.drawString("3", 90, 205);
g.drawString("4", 90, 265);
g.drawString("5", 90, 325);
g.drawString("6", 90, 385);
g.drawString("7", 90, 445);
g.drawString("8", 90, 505);
g.drawString("9", 90, 565);
g.drawString("10", 90, 625);
//Along the X-Axis
g.drawString("1", 135, 670);
g.drawString("2", 195, 670);
g.drawString("3", 255, 670);
g.drawString("4", 315, 670);
g.drawString("5", 375, 670);
g.drawString("6", 435, 670);
g.drawString("7", 495, 670);
g.drawString("8", 555, 670);
g.drawString("9", 615, 670);
//Draws a 3DRect around the top row of ellipse2D objects
g2.setColor(Color.lightGray);
g2.draw3DRect(120, 60, 580, 40, true);
g2.draw3DRect(121, 61, 578, 38, true);
g2.draw3DRect(122, 62, 576, 36, true);
}
/*
* MouseAdapter is extended for mousePressed Event that detects if the x, y coordinates
* of a drawn ellipse are clicked. If the color is INACTIVE it is changed to ACTIVE and
* vice versa.
*/
private class MyMouseAdapter extends MouseAdapter {
#Override
/*
* When mousePressed event occurs, the color is toggled between ACTIVE and INACTIVE
*/
public void mousePressed(MouseEvent e) {
Color c;
for (Ellipse2D ellipse : ellipses) {
if (ellipse.contains(e.getPoint())) {
c = (ellipseColorMap.get(ellipse) == INACTIVE_COLOR) ? ACTIVE_COLOR : INACTIVE_COLOR;
ellipseColorMap.put(ellipse, c);
}
}
repaint();
}
}
/*
* This method will set the dimensions of the JFrame equal to the preferred H x W
*/
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
/*
* Used for button click action to change all ellipses to ACTIVE_COLOR
*/
public void activateAll(){
for (Ellipse2D ellipse : ellipses){
ellipseColorMap.put(ellipse, ACTIVE_COLOR);
}
repaint();
}
/*
* Used for button click action to change all ellipses to INACTIVE_COLOR
*/
public void deactivateAll(){
for (Ellipse2D ellipse : ellipses){
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
repaint();
}
}
This method will set the dimensions of the JFrame equal to the preferred H x W
No it set the preferred size of the panel. The size of the frame will be the preferred size of all the components added to it plus the frame decorations (title bar, borders).
When I resize the window the Graphics2D objects reduce into a tiny rectangle.
The GridBagLayout respects the preferred size of the component. When there is not enough space to display the component it will shrink to its "minimum size".
You probably need to override the getMinimumSize() method to equal the preferred size. Then in this case the component should just be truncated if space is not available.
If you want you actually painting to shrink then you need to build the logic into your painting code so that the painting is done relative to the space available on the panel.
Try adding your 2D object to a JLabel as BufferedImage of ImageIcon. You can do this by:
JLabel label2 = new JLabel(new ImageIcon(//Location of your Image);
Or I think you can also add Graphics2D objects directly creating them inside label bu I'm not sure about that
This code is from a Java textbook by Lewis Loftus. It shows the example output in the textbook and the background is light blue (cyan). I think there is something wrong with:
setBackground(Color.cyan);
Here is the whole program:
import javax.swing.JApplet;
import java.awt.*;
public class Snowman extends JApplet
{
//-----------------------------------------------------------------
// Draws a snowman.
//-----------------------------------------------------------------
public void paint(Graphics page)
{
final int MID = 150;
final int TOP = 50;
setBackground(Color.cyan);
page.setColor(Color.blue);
page.fillRect(0, 175, 300, 50); // ground
page.setColor(Color.yellow);
page.fillOval(-40, -40, 80, 80); // sun
page.setColor(Color.white);
page.fillOval(MID-20, TOP, 40, 40); // head
page.fillOval(MID-35, TOP+35, 70, 50); // upper torso
page.fillOval(MID-50, TOP+80, 100, 60); // lower torso
page.setColor(Color.black);
page.fillOval(MID-10, TOP+10, 5, 5); // left eye
page.fillOval(MID+5, TOP+10, 5, 5); // right eye
page.drawArc(MID-10, TOP+20, 20, 10, 190, 160); // smile
page.drawLine(MID-25, TOP+60, MID-50, TOP+40); // left arm
page.drawLine(MID+25, TOP+60, MID+55, TOP+60); // right arm
page.drawLine(MID-20, TOP+5, MID+20, TOP+5); // brim of hat
page.fillRect(MID-15, TOP-20, 30, 25); // top of hat
}
}
Never try to draw in a top-level component. Instead, create a class that extends JPanel, override its paintComponent method, be sure to call the super's paintComponent within the override, and then add the JPanel to your JApplet's contentPane. Also, set the JPanel's background in its constructor, not in its paint or paintComponent method.
Also, in future questions, please try to indent your code a reasonable and consistent amount. Good code formatting makes the code much easier to read and more importantly, to understand.
e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
#SuppressWarnings("serial")
public class SnowManPanel extends JPanel {
private static final Color BACKGROUND = Color.CYAN;
private static final int MID = 150;
private static final int TOP = 50;
private static final int PREF_W = 300;
private static final int PREF_H = 225;
public SnowManPanel() {
setBackground(BACKGROUND);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
g.fillRect(0, 175, PREF_W, PREF_H - 175); // ground
g.setColor(Color.yellow);
g.fillOval(-40, -40, 80, 80); // sun
g.setColor(Color.white);
g.fillOval(MID-20, TOP, 40, 40); // head
g.fillOval(MID-35, TOP+35, 70, 50); // upper torso
g.fillOval(MID-50, TOP+80, 100, 60); // lower torso
g.setColor(Color.black);
g.fillOval(MID-10, TOP+10, 5, 5); // left eye
g.fillOval(MID+5, TOP+10, 5, 5); // right eye
g.drawArc(MID-10, TOP+20, 20, 10, 190, 160); // smile
g.drawLine(MID-25, TOP+60, MID-50, TOP+40); // left arm
g.drawLine(MID+25, TOP+60, MID+55, TOP+60); // right arm
g.drawLine(MID-20, TOP+5, MID+20, TOP+5); // brim of hat
g.fillRect(MID-15, TOP-20, 30, 25); // top of hat
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
SnowManPanel mainPanel = new SnowManPanel();
JFrame frame = new JFrame("SnowManPanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_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();
}
});
}
}
Note that top level windows such as JApplets and JFrames are a bit complex and have multiple roles as well as multiple layers. One problem is that your program tries to draw directly in the JApplet's paint method, ignoring that the background of the applet is drawn by another layer, by its contentPane, a JPanel that it holds all of the applet's content. By not calling the super.paint(...) method it also risks corrupting the applet's painting chain -- since the applet's own painting (called via the super.paint(...)) is ultimately responsible for painting all of the applet including its borders and its child components.
I am working on a class that can rotate a wheel around the center. The wheel is created using graphics2d, but I can not figure out exactly how to get the wheel to rotate around the center.
Currently, the wheel rotates, but not exactly about the origin.
My ultimate goal here is to create the wheel so that it is multicolored as well as a program around it, but my main concern here is getting the rotating wheel to work. If you could point me in the right direction I would be forever grateful!
Here is my current code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class RotateApp {
private static final int N = 3;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(N, N, N, N));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new RotatePanel());
frame.pack();
frame.setVisible(true);
System.out.println();
}
});
}
}
class RotatePanel extends JPanel implements ActionListener {
private static final int SIZE = 256;
private static double DELTA_THETA = Math.PI / 90;
private final Timer timer = new Timer(25, this);
private Image image = RotatableImage.getImage(SIZE);
private double dt = DELTA_THETA;
private double theta;
public RotatePanel() {
this.setBackground(Color.lightGray);
this.setPreferredSize(new Dimension(
image.getWidth(null), image.getHeight(null)));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
image = RotatableImage.getImage(SIZE);
dt = -dt;
}
});
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
g2d.rotate(theta);
g2d.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
g2d.drawImage(image, 0, 0, null);
}
public void actionPerformed(ActionEvent e) {
theta += dt;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
class RotatableImage {
private static final Random r = new Random();
static public Image getImage(int size) {
BufferedImage bi = new BufferedImage(
size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1));
g2d.setStroke(new BasicStroke(10.0f));
g2d.draw(new Line2D.Double(0, 100, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 200, 100));
g2d.draw(new Line2D.Double(100, 0, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 100, 200));
g2d.draw(new Line2D.Double(25, 25, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 175, 175));
g2d.draw(new Line2D.Double(175, 25, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 25, 175));
g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));
g2d.dispose();
return bi;
}
}
You can use the Rotated Icon class to do the rotation for you so you don't have to worry about all the rotation logic and the rotation logic is in a reusable class.
An example of using this class would be:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class Rotation4 extends JPanel
{
private JLabel label;
private RotatedIcon rotated;
private int degrees;
public Rotation4(Image image)
{
setLayout( new GridBagLayout() );
Icon icon = new ImageIcon( image );
rotated = new RotatedIcon(icon, 0);
rotated.setCircularIcon(true);
label = new JLabel(rotated);
label.setOpaque(true);
label.setBackground(Color.RED);
add(label, new GridBagConstraints());
setDegrees( 0 );
}
public void setDegrees(int degrees)
{
this.degrees = degrees;
rotated.setDegrees( degrees );
label.revalidate();
label.repaint();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
Image bi = RotatableImage.getImage(210);
final Rotation4 r = new Rotation4(bi);
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
r.setDegrees( value );
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(r));
f.add(slider, BorderLayout.SOUTH);
f.setSize(400, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
static class RotatableImage
{
private static final Random r = new Random();
static public Image getImage(int size)
{
BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1));
g2d.setStroke(new BasicStroke(10.0f));
g2d.draw(new Line2D.Double(5, 105, 205, 105));
g2d.draw(new Line2D.Double(105, 5, 105, 205));
g2d.draw(new Line2D.Double(35, 35, 175, 175));
g2d.draw(new Line2D.Double(175, 35, 35, 175));
g2d.draw(new Ellipse2D.Double(5, 5, 199, 199));
g2d.setColor(Color.BLACK);
g2d.fillOval(100, 100, 10, 10);
g2d.dispose();
return bi;
}
}
}
Note I also had to make changes with your image and your painting. These changes will need to be made whether you use the RotatedIcon or do the rotation code yourself:
The image size was changed to 210. This is because your stroke size is 10, so you need to account for the extra pixels in the circle outline.
You need to change the original of the circle by half the stroke size. So in this case the origin becomes (5, 5).
The size of the oval needs to be changed to 199. This is because of the way the outline of the oval is painted. 1 extra pixel is needed for the outline. If you leave the size at 200 then 1 pixel of the outline will be lost. This is not very noticeable when using a stroke size of 10, but if you use a size of 1, then the outline will be missing at the right and bottom edges.
The locations of your lines needs to be changes. you don't want the line right to the edge of the circle because then you will get a flat line at the edge instead of the rounded line. So I started the line 5 pixels from the start and ended it 5 pixels from the end.
Ok, with little modification and fewer "spokes", I got your wheel rotate centric (1.) and multicolor (2.):
UPDATE on 1.) To make centric rotation in your (original) code just chage SIZEto 200!
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class RotateApp {
private static final int N = 3;
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(N, N, N, N));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new RotatePanel());
frame.pack();
frame.setVisible(true);
System.out.println();
});
}
}
class RotatePanel extends JPanel implements ActionListener {
private static final int SIZE = 256;
private static final double DELTA_THETA = Math.PI / 90;
private final Timer timer = new Timer(25, this);
private Image image = RotatableImage.getImage(SIZE);
private double dt = DELTA_THETA;
private double theta;
public RotatePanel() {
this.setBackground(Color.lightGray);
this.setPreferredSize(new Dimension(SIZE, SIZE));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
dt = -dt;
image = RotatableImage.getImage(SIZE);
}
});
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.rotate(theta,128,128);
g2d.drawImage(image, 0, 0, null);
}
#Override
public void actionPerformed(ActionEvent e) {
theta += dt;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
class RotatableImage {
private static final Random r = new Random();
static public Image getImage(int size) {
BufferedImage bi = new BufferedImage(
size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
final Color c1 = Color.getHSBColor(r.nextFloat(), 1, 1);
final Color c2 = Color.getHSBColor(r.nextFloat(), 1, 1);
g2d.setPaint(c1);
g2d.setStroke(new BasicStroke(10.0f));
g2d.draw(new Line2D.Double(0, size/2, size, size/2));
g2d.setPaint(c2);
g2d.draw(new Line2D.Double(size/2, 0, size/2, size));
g2d.setPaint(c1);
g2d.draw(new Ellipse2D.Double(0, 0, size, size));
g2d.dispose();
return bi;
}
}
Explanation:
So the "wobble" in your solution came from the fact, that you sized the image and the container/panel 256x256, but "based" your wheel layout on 200x200 only. I fixed all dimensions, and drew a correct cross, the g2d.rotate(theta,128,128); (!) relates then to the center.
Multi-color(easy): You can invoke setPaint() between each shape! ;)
I have serious problem when I add JPanel to Oracle Forms Container (based-on AWT Container).
I add JPanel first, after that I add some VTextFields (Oracle Forms text field).
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import oracle.ewt.scrolling.scrollBox.ScrollBox;
import oracle.forms.ui.DrawnPanel;
import oracle.forms.ui.FScrollBox;
import oracle.forms.ui.VTextField;
public class OverlapTest {
int w = 800;
int h= 700;
public OverlapTest() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(w, h);
DrawnPanel main = new DrawnPanel();
main.setLayout(null);
main.setBounds(0, 0, w, h);
main.setVisible(true);
VTextField t1 = new VTextField();
t1.setBounds(100, 100, 130, 22);
VTextField t2 = new VTextField();
t2.setBounds(100, 150, 130, 22);
VTextField t3 = new VTextField();
t3.setBounds(100, 200, 130, 22);
final JPanel draw = new JPanel(){
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillRect(0, 100, 130, 200);
g2.dispose();
}
#Override
public void update(Graphics g) {
paint(g);
}
};
draw.setOpaque(false);
draw.setBounds(0, 0, w, h);
main.add(draw);
main.add(t1);
main.add(t2);
main.add(t3);
ScrollBox sBox = new ScrollBox(main);
sBox.setBounds(0, 0, w, h);
sBox.setVScrollInsets(1, 100);
oracle.forms.ui.FScrollBox fBox = new FScrollBox(sBox, 0, 0);
fBox.setVisible(true);
fBox.setBounds(0, 0, w - 50, h - 50);
main.setComponentZOrder(draw, 3);
main.setComponentZOrder(t1, 0);
main.setComponentZOrder(t2, 1);
main.setComponentZOrder(t3, 2);
f.add(fBox);
f.setVisible(true);
}
public static void main(String[] args) {
OverlapTest test = new OverlapTest();
}
}
As you see, I add the JPanel first, after that I setComponentZorder, that is because my requirement and in my real application I cannot add JPanel at the end of all component, so I did it follow that way.
But currently I have one problem, all other component overlap the JPanel but the background of JPanel (the red rectangle) always hide other components like that.
This is the image:
I don't know, but when I use JTextField, everything is OK.
I'm using components of Oracle Forms in frmall.jar
You can download frmall.jar from http://www.megafileupload.com/en/file/329640/frmall-jar.html
Do you have any solution to make the red rectangle is overlapped by other components?
Sorry for my terible English.
Thanks in Advance.
now I try to replace Jpanel by Forms DrawnPanel, but it still have the problem:
FormCanvas form = new FormCanvas(){
#Override
public void paint(Graphics g, Dimension paramDimension,
Rectangle paramRectangle) {
// TODO Auto-generated method stub
super.paint(g, paramDimension, paramRectangle);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillRect(0, 100, 200, 200);
g2.dispose();
}
};
DrawnPanel draw = new DrawnPanel();
draw.setPainter(form);
draw.setVisible(true);
So now, every my components are Forms Component, but I still get this problem
The first advice I would offer is don't mix Swing & AWT components. Try updating the 'Oracle forms' jar to a Swing version, or failing that, use only AWT components in your code.