I am working on a project to make a JApplet's contents automatically scale to the size specified in the html. I realize this is the kind of thing that layout managers were made for, however as I am not permitted to rewrite the entire applets structure, i decided i would try to override paint and simply set the AffineTransform of the Graphics object to an appropriately scaled version, then capture mouse Events in the top container and scale them back with an appropriate scaling transform. Im getting stuck on the drawing part at the moment. When viewed in a web browser, it renders the scaled version correctly once, then the image is shrunk back to its original size. In addition, it seems that the paint method in JApplet is only ever called once. Here is a cropped version of my code which focuses on the problem. Any help would be appreciated. Thanks in advance.
import javax.swing.JApplet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
public class Test extends JApplet
{
public static final int ORIGINAL_APPLET_WIDTH = 1024;
public static final int ORIGINAL_APPLET_HEIGHT = 800;
private AffineTransform scalingTransform;
private AffineTransform inverseScalingTransform;
#Override
public void init()
{
double xFactor = ((double)(this.getWidth()))/((double)(Test.ORIGINAL_APPLET_WIDTH));
double yFactor = ((double)(this.getHeight()))/((double)(Test.ORIGINAL_APPLET_HEIGHT));
this.scalingTransform = new AffineTransform();
this.inverseScalingTransform = new AffineTransform();
this.scalingTransform.scale(xFactor,yFactor);
this.inverseScalingTransform.scale(1D/xFactor,1D/yFactor);
}
#Override
public void paint(Graphics g)
{
((Graphics2D)g).setTransform(Test.this.scalingTransform);
super.paint(g);
}
}
I figured out, after much research, that the problem was that JApplet's paint method doesn't get called very often. The instead the content pane has its own drawing surface, so i simply had to replace the content pane to get it to upload. heres the way i did it:
#Override
public void init()
{
double xFactor = ((double)(this.getWidth()))/((double)(qt.ORIGINAL_APPLET_WIDTH));
double yFactor = ((double)(this.getHeight()))/((double)(qt.ORIGINAL_APPLET_HEIGHT));
this.scalingTransform = new AffineTransform();
this.inverseScalingTransform = new AffineTransform();
this.scalingTransform.scale(xFactor,yFactor);
this.inverseScalingTransform.scale(1D/xFactor,1D/yFactor);
JPanel drawScale = new JPanel()
{
#Override
public void paint(Graphics g)
{
((Graphics2D)g).setTransform(Test.this.scalingTransform);
super.paint(g);
}
#Override
public void paintAll(Graphics g)
{
((Graphics2D)g).setTransform(Test.this.scalingTransform);
super.paintAll(g);
}
#Override
public void paintComponents(Graphics g)
{
((Graphics2D)g).setTransform(Test.this.scalingTransform);
super.paintComponents(g);
}
#Override
public void paintComponent(Graphics g)
{
((Graphics2D)g).setTransform(Test.this.scalingTransform);
super.paintComponents(g);
}
};
Container oldPane = this.getContentPane();
drawScale.setLayout(oldPane.getLayout());
this.setContentPane(drawScale);
}
these paint methods were of course in addition to the ones in the applet.
Related
From another class I load a image, which represents a map, using JFileChooser. In the new frame, I will have the image, I will load data for the images (like the coordinates of the corners), and after that I need to draw the distance on the map and zoom that image with the lines on it.
The problem I have is that the paintComponent function doesn't show me anything, it doesn't even go into it (I try to load it using menubar). And the next problem is that I don't know exactly how I should zoom in on the image with the drawn distances.
At this moment I only have the image with the map and the zoom applied to it.
I have an actionPerformed for an item from menubar:
public void actionPerformed(ActionEvent e) {
...
if(e.getSource()==addR)
{
add( new RoutePane());
}
}
The RoutePane class is ():
#SuppressWarnings("serial")
class RoutePane extends JPanel{
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D gr = (Graphics2D) g;
int x=10;
gr.setColor(Color.BLACK);
for(int i=0; i<10; i++) {
gr.drawLine(x,x,x+10,x+10);
x+=10;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1200, 700);
}
}
The zoom method that I have is from this website: (https://coderanch.com/t/338284/java/zoom-zoom-picture-swing)
I am trying to draw to a single panel from multiple sources in java. However when I try this test code I get applet not initialized. Keeping in mind I am fairly new to this. How would I get rid of this error and or draw to a panel from multiple sources.
import java.awt.Graphics;
import javax.swing.JPanel;
class Surface extends JPanel {
public void init() {
}
public void paintComponent(Graphics g){
super.paintComponent(g);
DrawRect d = new DrawRect(this);
d.draw( g );
}
}
class DrawRect {
Surface surface;
Graphics g;
public DrawRect(Surface surface)
{
g = surface.getGraphics();
}
public void draw( Graphics g )
{
g.fillRect(20,20,100,50); // (now this will work).
}
}
I'm trying to pass a graphics element up the chain. I need to have the ability to draw a number of different die and return the correct one for each instance. I can get this to compile but I don't know if i'm doing this correctly. I want to pass the graphics component to a panel to be displayed.
My shortened paint class
import java.awt.*;
import javax.swing.*;
class DiePaint extends JPanel
{
Graphics g;
public Graphics dieSwitch(int inInt)
{
return die1();
}
private Graphics die1()
{
//reset drawing
repaint();
//draw a die with 1 pip
g.setColor(Color.BLACK);
g.drawRect(0,0,50,50);
g.drawOval(24,24,2,2);
g.fillOval(24,24,2,2);
//return graphic
return g;
}
}
A method in my other class i'm trying to use to call it.
private void setDie()
{
//set die labels
die1P.paint(drawDie.dieSwitch(game.getDie(0)));
}
"I want to pass the graphics component to a panel to be displayed."
No, you don't.
You need to see how to Perform Custom Painting. You're going to need a paintComponent method in your panel
#Override
protected void paintComponent(Graphic s) {
super.paintComponent(g);
// draw here
}
You don't explicitly call paint like you are doing here die1P.paint(drawDie.dieSwitch
If you want to be able to set what is being painted, you can have a Die object that you use to draw. Something like
class Die {
public void draw(Graphics g) {
// draw die here
}
}
Then in your panel class have a setter for the Die object, that will repaint the new Die. You will probably want to have a way to differentiate each die. Pass some arguments to a constructor to do that. Then paint the one die.
public class DiePanel extends JPanel {
private Die die;
public void setDie(Die die) {
this.die = die;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (die != null) {
die.draw(g);
}
}
}
You may also, instead, want to make Die an interface, so you can implement difference Die objects, like DieOne, DieTwo, etc. Something like
public interface Die {
void Draw(Grapchis g);
}
public class DieOne {
#Override
public void draw(Graphics g) {
// draw die one
}
}
When you call setDie(), you can pass a specific Die, like
DieOne dieOne = new DieOne();
...
diePanel.setDie(dieOne);
Yes you can pass the drawn component by using BufferedImage....first you draw the graphic on this BufferedImage then pass this image and then draw this image to the Panel...Here is the code:
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
class DiePaint extends JPanel
{
int width=500; int height=500; //you can change as requred
BufferedImage buffg=new BufferedImage(width,height , BufferedImage.TYPE_INT_ARGB);
Graphics g;
public BufferedImage dieSwitch(int inInt) //change return type to BufferedImage
{
return die1();
}
private BufferedImage die1() // change return type to BufferedImage
{
g=buffg.getGraphics(); //get Graphics from buffg..
//reset drawing
repaint();
//draw a die with 1 pip
g.setColor(Color.BLACK); //draw all the component on buffg using its Graphics g
g.drawRect(0,0,50,50);
g.drawOval(24,24,2,2);
g.fillOval(24,24,2,2);
//return graphic
return buffg;
}
}
now once you get this "buffg" now you can draw it on any panel.....
JPanel p=new JPanel(){
#Override
public void paint(Graphics g){
g.drawImage(drawDie.dieSwitch(game.getDie(0))); //get & draw Image
}
};
Alright the deal is I am trying to use the drawPie method to create my pie chart in an applet. After attempting google searches I find multiple tutorials that explain part of the process but not all of it. While trying to knit together partial information I am not getting the results I want.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JApplet;
import javax.swing.JComponent;
public class JLW_PieApplet extends JApplet {
class PieData extends JComponent {
PieValue[] slices = new PieValue[4];
PieData() {
slices[0] = new PieValue(35, Color.red);
slices[1] = new PieValue(33, Color.green);
slices[2] = new PieValue(20, Color.pink);
slices[3] = new PieValue(12, Color.blue);
}
public void paint(Graphics g) {
drawPie((Graphics2D)g, getBounds(), slices);
}
}
}
Ther isn't such method in Swing called drawPie. Without the contents of this method, we have no idea of how to help you
Try having a read through 2D Graphics and have a look at Ellipse2D in particular
The other problem I can see is you don't call super.paint(g) in your paint method. This is VERY, VERY, VERY important
You have a PieData component within your applet but you never add it, so you need to add it in init and bring in drawPie from your link above:
public class JLW_PieApplet extends JApplet {
public void init() {
add(new PieData());
}
class PieData extends JComponent {
PieValue[] slices = new PieValue[4];
PieData() {
slices[0] = ...
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawPie((Graphics2D) g, getBounds(), slices);
}
public void drawPie(Graphics2D g, Rectangle area, PieValue[] slices) {
...
I am attempting to create two components that each have a paintComponent() method -- The goal being that the parent object will paint default art, and the child object can then paint over it. An example could be creating playing cards: you have a parent Card class which paints a default card, then suite-specific classes which extend Card and paint their details on top of it.
Here is a diagram of what I am trying to accomplish:
Here is the code I am working with. My specific problem is: when the component is drawn -- if the child class does not have a paintComponent method -- the parents art is drawn. However, if I implement a paintComponent method on the child, the parents is not drawn, only the childs.
Here is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
abstract public class Tile extends JPanel {
public static final int DEFAULT_WIDTH = 100;
public static final int DEFAULT_HEIGHT = 100;
#Override public void paintComponent(Graphics g){
//Set Size
setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
Graphics2D g2 = (Graphics2D)g;
//Draw default art
}
#Override public Dimension getMinimumSize()
{ return new Dimension(DEFAULT_WIDTH,DEFAULT_HEIGHT); }
#Override public Dimension getPreferredSize()
{ return getMinimumSize(); }
//.....
}
import javax.swing.*;
import java.awt.*;
public class CharacterTile extends Tile {
protected char symbol;
public CharacterTile(char symbol){
this.symbol = symbol;
}
#Override public void paintComponent(Graphics g){
super.paintComponents(g);
Graphics2D g2 = (Graphics2D)g;
//Draw details
}
//.....
}
It's not a good use of inheritance. You should have something like:
Card
{
Art front;
Art back;
paintComponent()
{
back.paintComponent();
front.paintComponent();
}
}
You could even have a List layers; and paint all the layers you need.
Sub classing is for splitting your code into smaller problems. For reusing code you should use polymorphism + object composition.