I save an image in a String, then when I open it it's always 300x150
Why is the image truncated?
Where does 300x150 come from?
The code is what you see. Just 2 buttons.
The first one saves the image in "png", and the other reads the image from "png"
Button save = new Button("copy");
save.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
ImageElement imageElement = ImageElement.as(image.getElement());
Canvas canvasTmp = Canvas.createIfSupported();
Context2d context = canvasTmp.getContext2d();
context.drawImage(imageElement, 0.0, 0.0, imageElement.getWidth(), imageElement.getHeight());
png = canvasTmp.toDataUrl("image/png");
}
});
Button open = new Button("open");
open.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
final Image image = new Image(png);
vp.add(image);
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event)
{
Window.alert("ok");
}
});
image.addErrorHandler(new ErrorHandler() {
#Override
public void onError(ErrorEvent event) {
Window.alert("error");
}
} );
}
});
The canvas has a default width of 300 pixels and a default height of 150 pixels. After creating the canvas and before drawing the image, consider doing this:
int width = imageElement.getWidth()
int height = imageElement.getHeight()
canvasTmp.setWidth(width + "px");
canvasTmp.setHeight(height + "px");
canvasTmp.setCoordinateSpaceWidth(width);
canvasTmp.setCoordinateSpaceHeight(height);
Related
I have a difficult situation.
I'm making a 2D game and I'm on the step
of integrating box2Dlights part.
But when i'm rendering my RayHandler, I have a black screen.
Here is another image, where I don't render my lights. There is no lights now.
I need to have collision of Box2D and Box2Dlights mixed together.
Please note:
All my boxes are made in units, equal to 1, so that one room is 16 squares length.
All entire world is zoomed by setToOrtho((16 - 1.875f) / Gdx.graphics.getHeight()), where 16 is tile size.
If I scaled my tile size, I would like to have this stuff work.
All code is complicated so I send the only GameScreen and GameMap classes for now:
#Override
public void show() {
InstanceVars inst = InstanceVars.getInstance();
inst.world = new World(new Vector2(0, 0f), true);
inst.engine = new Engine();
inst.handler = new RayHandler(inst.world);
LevelCreator creator = new LevelCreator("level_def.cfg");
try {
gameWorld = creator.createNewLevel();
gameWorld.start();
} catch (FileCorruptedException e) {
e.printStackTrace();
}
}
#Override
public void render(float delta) {
gameWorld.render();
}
#Override
public void resize(int width, int height) {
gameWorld.resize(width, height);
}
#Override
public void dispose() {
gameWorld.dispose();
InstanceVars.getInstance().dispose();
}
for the GameScreen.java
and
private World physWorld = InstanceVars.getInstance().world;
private Box2DDebugRenderer physRender = new Box2DDebugRenderer();
private OrthographicCamera cam = new OrthographicCamera();
private RayHandler lights = new RayHandler(physWorld);
private PlayerController controls;
private float STD_ZOOM = ((float) CELL_SIZE + 16) / Gdx.graphics.getHeight();
private Body playerBody;
public GameMap() {
cam.zoom = STD_ZOOM;
}
public void start() {
GameObject player = (GameObject) getProperties().get("ent_player");
playerBody = player.getComponent(PhysicsComponent.class).getBody();
controls = new PlayerController();
Gdx.input.setInputProcessor(controls);
physWorld.setContactListener(new CollisionInteractor(InstanceVars.getInstance().engine));
PointLight light = new PointLight(lights, 1000, Color.GOLDENROD, 500, playerBody.getPosition().x, playerBody.getPosition().y);
}
public void render() {
updatePlayer();
physWorld.step(1/60f, 8, 2);
updateCamera();
physRender.render(physWorld, cam.combined);
// lights.updateAndRender();
}
private void updatePlayer() {
if (controls.up) playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, -controls.speed);
else playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, controls.down ? controls.speed : 0);
if (controls.down) playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, controls.speed);
else playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, controls.up ? -controls.speed : 0);
if (controls.left) playerBody.setLinearVelocity(-controls.speed, playerBody.getLinearVelocity().y);
else playerBody.setLinearVelocity(controls.right ? controls.speed : 0, playerBody.getLinearVelocity().y);
if (controls.right) playerBody.setLinearVelocity(controls.speed, playerBody.getLinearVelocity().y);
else playerBody.setLinearVelocity(controls.left ? -controls.speed : 0, playerBody.getLinearVelocity().y);
}
public void resize(float width, float height) {
STD_ZOOM = ((float) CELL_SIZE - 1.875f) / Gdx.graphics.getHeight();
cam.setToOrtho(true, width, height);
}
private void updateCamera() {
cam.position.set(playerBody.getPosition(), 0);
cam.update();
}
public void dispose() {
super.dispose();
physWorld.dispose();
physRender.dispose();
}
for GameMap.java.
If you need more details, don't be afraid to ask.
I cannot solve the problem on my own.
What does parameter targetWidth exactly means here and what it has to do with wrap parameter?
public GlyphLayout (BitmapFont font, CharSequence str, Color color, float targetWidth, int halign, boolean wrap) {
setText(font, str, color, targetWidth, halign, wrap);
}
From doc :
targetWidth : The width used for alignment, line wrapping, and truncation. May be zero if those features are not used.
wrap : If true then (a word or unit of text) to be carried over to a new line automatically as the margin is reached, or to fit around embedded features.
If false, the text will only wrap where it contains newlines (\n).
EDIT
Test code : Practical demonstration, how targetWidth and wrap works in GlyphLayout constructor.
public class MyGdxGame extends ApplicationAdapter {
private GlyphLayout glyphLayout[];
private BitmapFont bitmapFont;
private float targetWidth=250;
private ShapeRenderer shapeRenderer;
private SpriteBatch spriteBatch;
private float xPos[]={450,450,450,30,450,880};
private float yPos[]={550,480,410,340,340,340};
#Override
public void create () {
spriteBatch=new SpriteBatch();
shapeRenderer=new ShapeRenderer();
shapeRenderer.setAutoShapeType(true);
bitmapFont=new BitmapFont(Gdx.files.internal("skin/poet.fnt"));
glyphLayout=new GlyphLayout[6];
glyphLayout[0]=new GlyphLayout(bitmapFont, "LOADING SCREENsssssssssssssssssssssssssssssssssssss", Color.BLACK, targetWidth, Align.left, false);
glyphLayout[1]=new GlyphLayout(bitmapFont, "LOADING SCREENsssssssssssssssssssssssssssssssssssss", Color.BLACK, targetWidth, Align.right, false);
glyphLayout[2]=new GlyphLayout(bitmapFont, "LOADING SCREENsssssssssssssssssssssssssssssssssssss", Color.BLACK, targetWidth, Align.center, false);
glyphLayout[3]=new GlyphLayout(bitmapFont, "LOADING SCREENsssssssssssssssssssssssssssssssssssss", Color.BLACK, targetWidth, Align.left, true);
glyphLayout[4]=new GlyphLayout(bitmapFont, "LOADING SCREENsssssssssssssssssssssssssssssssssssss", Color.BLACK, targetWidth, Align.right, true);
glyphLayout[5]=new GlyphLayout(bitmapFont, "LOADING SCREENsssssssssssssssssssssssssssssssssssss", Color.BLACK, targetWidth, Align.center, true);
}
#Override
public void render() {
Gdx.gl.glClearColor(1f, 0f, 0f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
for (int i=0;i<glyphLayout.length;i++) {
bitmapFont.draw(spriteBatch, glyphLayout[i], xPos[i], yPos[i]);
}
spriteBatch.end();
shapeRenderer.begin();
shapeRenderer.setColor(Color.BLUE);
shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
for (int i=0;i<glyphLayout.length;i++) {
shapeRenderer.rectLine(xPos[i], yPos[i], xPos[i] + targetWidth, yPos[i], 3f);
}
shapeRenderer.end();
}
#Override
public void dispose () {
bitmapFont.dispose();
shapeRenderer.dispose();
spriteBatch.dispose();
}
}
Output :
Target width is the lenient maximum width that the text will be before it is wrapped, truncated or otherwise altered from being a single line.
e.g. Consider a string of width 500 (when drawn). With a target width of 250, it will be wrapped at ~250 into 2 lines (if wrap is true).
I've made a simple Media Player for an application I'm working on, the problem is that I thought that you could simply integrate JavaFX into Swing. Which is not the case. I have been searching for a solution to this problem and tried to use this website: http://docs.oracle.com/javafx/2/swing/jfxpub-swing.htm
The problem is that even though I have the website that explains how to put the code together, I still don't understand how. Here is the mediaplayer and I plan to integrate it into my Swing code, so that I can call the media player when a button is clicked. Here is all my code for the media player and if anyone can share some light on how to integrate it into my Swing code i.e my GUI, I would probably have to kiss you through the computer.
public class Player extends Application{
private boolean atEndOfMedia = false;
private final boolean repeat = false;
private boolean stopRequested = false;
private Duration duration;
private Label playTime;
private Slider volumeSlider;
#Override
public void start(final Stage stage) throws Exception {
stage.setTitle("Movie Player");//set title
Group root = new Group();//Group for buttons etc
final Media media = new Media("file:///Users/Paul/Downloads/InBruges.mp4");
final MediaPlayer playa = new MediaPlayer(media);
MediaView view = new MediaView(playa);
//Slide in and out and what causes that.
final Timeline slideIn = new Timeline();
final Timeline slideOut = new Timeline();
root.setOnMouseEntered(new javafx.event.EventHandler<javafx.scene.input.MouseEvent>() {
#Override
public void handle(MouseEvent t) {
slideIn.play();
}
});
root.setOnMouseExited(new javafx.event.EventHandler<javafx.scene.input.MouseEvent>() {
#Override
public void handle(MouseEvent t) {
slideOut.play();
}
});
final VBox vbox = new VBox();
final Slider slider = new Slider();
final Button playButton = new Button("|>");
root.getChildren().add(view);
root.getChildren().add(vbox);
vbox.getChildren().add(slider);
vbox.getChildren().add(playButton);
vbox.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 400, 400, Color.BLACK);
stage.setScene(scene);
stage.show();
// Play/Pause Button
playButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
Status status = playa.getStatus();
if (status == Status.UNKNOWN || status == Status.HALTED)
{
// don't do anything in these states
return;
}
if ( status == Status.PAUSED
|| status == Status.READY
|| status == Status.STOPPED)
{
// rewind the movie if we're sitting at the end
if (atEndOfMedia) {
playa.seek(playa.getStartTime());
atEndOfMedia = false;
}
playa.play();
} else {
playa.pause();
}
}
});
//Listeners and Shit for Play Button
playa.setOnPlaying(new Runnable() {
#Override
public void run() {
if (stopRequested) {
playa.pause();
stopRequested = false;
} else {
playButton.setText("||");
}
}
});
playa.setOnPaused(new Runnable() {
#Override
public void run() {
playButton.setText(">");
}
});
playa.play();
playa.setOnReady(new Runnable() {
#Override
public void run(){
int v = playa.getMedia().getWidth();
int h = playa.getMedia().getHeight();
stage.setMinWidth(v);
stage.setMinHeight(h);
vbox.setMinSize(v, 100);
vbox.setTranslateY(h-50);
//slider and graphical slide in/out
slider.setMin(0.0);
slider.setValue(0.0);
slider.setMax(playa.getTotalDuration().toSeconds());
slideOut.getKeyFrames().addAll(
new KeyFrame(new Duration(0),
new KeyValue(vbox.translateYProperty(), h-100),
new KeyValue(vbox.opacityProperty(), 0.9)
),
new KeyFrame(new Duration(300),
new KeyValue(vbox.translateYProperty(), h),
new KeyValue(vbox.opacityProperty(), 0.0)
)
);
slideIn.getKeyFrames().addAll(
new KeyFrame(new Duration(0),
new KeyValue(vbox.translateYProperty(), h),
new KeyValue(vbox.opacityProperty(), 0.0)
),
new KeyFrame(new Duration(300),
new KeyValue(vbox.translateYProperty(), h-100),
new KeyValue(vbox.opacityProperty(), 0.9)
)
);
}
});
//Slider being current and ability to click on slider.
playa.currentTimeProperty().addListener(new ChangeListener<Duration>(){
#Override
public void changed(ObservableValue<? extends Duration> observableValue, Duration duration, Duration current){
slider.setValue(current.toSeconds());
}
});
slider.setOnMouseClicked(new javafx.event.EventHandler<javafx.scene.input.MouseEvent>() {
#Override
public void handle(javafx.scene.input.MouseEvent t) {
playa.seek(Duration.seconds(slider.getValue()));
}
});
}
Use JFXPanel:
public class Test {
private static void initAndShowGUI() {
// This method is invoked on Swing thread
JFrame frame = new JFrame("FX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);
Platform.runLater(new Runnable() {
#Override
public void run() {
initFX(fxPanel);
}
});
}
private static void initFX(JFXPanel fxPanel) {
// This method is invoked on JavaFX thread
Scene scene = createScene();
fxPanel.setScene(scene);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initAndShowGUI();
}
});
}
}
where method createScene() is start(final Stage stage) from your code.
Just instead of putting scene to stage you return it.
I've written an app that custom draws everything inside paint() based on fixed pixel positions. Then I disabled resize of the frame so its always visible.
However, now I would like to be able to resize it but I dont want to change my drawling code. I was hoping I could grab the 300x300 square of the Graphics g object and resize it to the JFrame current size after all of my drawling code, but I have no idea what I'm doing.
Here sample code. In this I want the 100x100 square to remain in the middle, proportionate to the resized JFrame:
package DrawAndScale;
import java.awt.Color;
import java.awt.Graphics;
public class DASFrame extends javax.swing.JFrame {
public DASFrame() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DASFrame().setVisible(true);
}
});
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fill3DRect(100, 100, 100, 100, true);
}
}
Thanks.
Assuming you rename your method that paints for 300x300 as paint300, define a buffered image:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300); // empty image
paint300(bufferImage.getGraphics()); // fill the image
g.drawImage(bufferImage, 0, 0, null); // send the image to graphics device
}
Above is when you want to draw at full size (300x300).
If your window is resized:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300);
paint300(bufferImage.getGraphics());
int width = getWidth();
int height = getHeight();
CropImageFilter crop =
new CropImageFilter((300 - width)/2, (300 - height)/2 , width, height);
FilteredImageSource fis = new FilteredImageSource(bufferImage, crop);
Image croppedImage = createImage(fis);
g.drawImage(croppedImage, 0, 0, null);
}
The new classes are from from java.awt.image.*.
I didn't test this code. It's just to send you in the right direction.
if you want to painting Custom paint then look for JLabel or JPanel and including Icon/ImageIcon inside, simple example about that
import java.awt.*;
import javax.swing.*;
public class MainComponentPaint extends JFrame {
private static final long serialVersionUID = 1L;
public MainComponentPaint() {
setTitle("Customize Preffered Size Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void display() {
add(new CustomComponent());
pack();
setMinimumSize(getSize());
setPreferredSize(getSize());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
setVisible(true);
}
});
}
public static void main(String[] args) {
MainComponentPaint main = new MainComponentPaint();
main.display();
}
}
class CustomComponent extends JComponent {
private static final long serialVersionUID = 1L;
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
for (int i = 0; i < Math.max(w, h); i += 20) {
g.drawLine(i, 0, i, h);
g.drawLine(0, i, w, i);
}
}
}
Not an expert, but you could just scale the Graphics2D object (the passed Graphics is in fact a Graphics2D instance), where the x and y ratios are the ratios of the fixed size you chose to draw and the actual size of the frame.
See http://download.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#scale%28double,%20double%29
You could do this with some math.
public void paint(Graphics g){
int height = 100;
int width = 100;
int x = (this.getWidth() / 2) - (width / 2);
int y = (this.getHeight() / 2) - (height / 2);
g.setColor(Color.BLACK);
g.fill3DRect(x, y, width, height, true);
}
Or if you wanted to keep the width and height of the box with the same proportion, use int width = this.getWidth() / 3; and int height = this.getHeight() / 3.
The other option is to use Graphics2D.scale(), as JB pointed out, the passed Graphics object is actually a Graphics2D object.
I have to load a small icon on the botton of my software. just to have a loading/ok/error icon. as sudgested on "http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter06/images.html" i create a dwowing panel extending JPanel.
class drawingPanel extends JPanel
{
Image img;
drawingPanel (Image img){
this.img = img;
}
public void paintComponent (Graphics g) {
super.paintComponent (g);
// Use the image width & height to find the starting point
int imgX = getSize ().width/2 - img.getWidth (this);
int imgY = getSize ().height/2 - img.getHeight (this);
//Draw image centered in the middle of the panel
g.drawImage (img, imgX, imgY, this);
} // paintComponent
}
I initialize the component in the following way:
// Grab the image.
Image img = new ImageIcon(iconPath+"ok.png").getImage();
// Create an instance of DrawingPanel
iconPanel = new drawingPanel(img);
all works well but at runtime i want to be able to change the icon within the pannel. i tryed all the fo;llowing but none managed to view the new picture:
Image img = new ImageIcon(iconPath+"loading.gif").getImage();
// Create a new instance of DrawingPanel
this.iconPanel = new drawingPanel(img);
this.iconPanel.repaint();
this.iconPanel.revalidate();
this.iconPanel.repaint();
this.repaint();
this.revalidate();
(i tryed this because the class in whic i am writing the code is another extension of JPanel that contains IconPanel. Any idea about why i do not manage to change the picture?
Thanks,
Stefano
First thing don't start class name with small name. Rename drawingPanel to DrawingPanel.
I have tried making a simple demo based on your description and it works fine. The image in panel is changing perfectly.
public class Demo {
public Demo() {
JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
// Grab the image.
Image img = new ImageIcon("1.png").getImage();
// Create an instance of DrawingPanel
final DrawingPanel iconPanel = new DrawingPanel(img);
frame.add(iconPanel, BorderLayout.CENTER);
JButton button = new JButton("Change image..");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
iconPanel.setImg(new ImageIcon("2.png").getImage());
iconPanel.repaint();
}
});
frame.setVisible(true);
}
public static void main(String[] args){
new Demo();
}
}
class DrawingPanel extends JPanel {
Image img;
DrawingPanel(Image img) {
this.img = img;
}
public void setImg(Image img) {
this.img = img;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Use the image width & height to find the starting point
int imgX = getSize().width / 2 - img.getWidth(this);
int imgY = getSize().height / 2 - img.getHeight(this);
// Draw image centered in the middle of the panel
g.drawImage(img, imgX, imgY, this);
} // paintComponent
}
The changes I have made is add a setter method of img in DrawingPanel class. So instead of creating new DrawingPanel you just have to call setImg() with new Image and then call reapint to paint the new image.