After extensive googling I've found that this issue is generally case-specific. I've tried many of the solutions found and none of them have worked for me, so I felt it was appropriate to create a post on it.
I'm using setJMenuBar and the bar is never appearing, here is my code:
NOTE: I believe the cause is that I update the frame, however the solution is still unknown.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
#SuppressWarnings("serial")
public class testclass extends JFrame {
public int updateRate = 60;
public int screenWidth;
public int screenHeight;
public boolean finishedInitialPaint;
private Graphics bufferGraphics;
private BufferStrategy bufferStrategy;
public int gridSize = 10;
JMenuBar engineBar;
JMenu fileMenu, editMenu, createMenu, toolsMenu, panelsMenu;
JMenuItem fileNewScene, fileOpenScene, fileSaveScene, fileExit;
JMenuItem editPreferences, editEngine;
JMenuItem createEmpty, createStandard;
JMenuItem toolsDebug;
JMenuItem panelView2D, panelEditor2D, panelHierarchy, panelInspector, panelExplorer;
public static void main(String[] args) {
testclass testClassv = new testclass ();
}
public testclass () {
Start ();
while(true) {
Update ();
ClearBackBuffer ();
try {
Thread.sleep(1000 / updateRate);
} catch (InterruptedException e) {
}
}
}
private void Start () {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
screenWidth = screenSize.width;
screenHeight = screenSize.height;
CreateDefaultEngineMenu ();
setTitle("Test Window");
setSize(Math.round(screenWidth * 0.99f), Math.round(screenHeight * 0.9f));
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void CreateDefaultEngineMenu () {
engineBar = new JMenuBar ();
/*
* Building initial menus
*/
// Build the file menu
fileMenu = new JMenu("File");
engineBar.add(fileMenu);
// Build the edit menu
editMenu = new JMenu("Edit");
engineBar.add(editMenu);
// Build the create menu
createMenu = new JMenu("Create");
engineBar.add(createMenu);
// Build the tools menu
toolsMenu = new JMenu("Tools");
engineBar.add(toolsMenu);
// Build the panels menu
panelsMenu = new JMenu("Panels");
engineBar.add(panelsMenu);
/*
* Building menu options
*/
// File menu options
fileNewScene = new JMenuItem("New Scene");
fileMenu.add(fileNewScene);
fileOpenScene = new JMenuItem("Open Scene");
fileMenu.add(fileOpenScene);
fileSaveScene = new JMenuItem("Save Scene");
fileMenu.add(fileSaveScene);
fileExit = new JMenuItem("Exit");
fileMenu.add(fileExit);
// Edit menu options
editPreferences = new JMenuItem ("Preferences");
editMenu.add(editPreferences);
editEngine = new JMenuItem ("Engine Settings");
editMenu.add(editEngine);
// Create menu options
createEmpty = new JMenuItem("New Empty GameObject");
createMenu.add(createEmpty);
createStandard = new JMenuItem("Standard GameObjects");
createMenu.add(createStandard);
// Tools menu options
toolsDebug = new JMenuItem ("Debug");
toolsMenu.add(toolsDebug);
// Panels menu options
panelView2D = new JMenuItem("View 2D");
panelsMenu.add(panelView2D);
panelEditor2D = new JMenuItem("Editor 2D");
panelsMenu.add(panelEditor2D);
panelHierarchy = new JMenuItem("Hierarchy");
panelsMenu.add(panelHierarchy);
panelInspector = new JMenuItem("Inspector");
panelsMenu.add(panelInspector);
panelExplorer = new JMenuItem("Explorer");
panelsMenu.add(panelExplorer);
// Set the frame to use the bar
setJMenuBar(engineBar);
}
private void Update () {
//sceneObjects.activeObjects.get(0).transform.position.x += 0.1f;
initialize ();
ClearBackBuffer ();
repaint ();
DrawBackBufferToScreen ();
}
private void initialize () {
if(bufferStrategy == null) {
this.createBufferStrategy(2);
bufferStrategy = this.getBufferStrategy();
bufferGraphics = bufferStrategy.getDrawGraphics();
}
}
public void paint(Graphics g) {
// Something to go here
}
private void ClearBackBuffer () {
bufferGraphics = bufferStrategy.getDrawGraphics();
try {
bufferGraphics.clearRect(0, 0, this.getSize().width, this.getSize().height);
Graphics2D g2d = (Graphics2D)bufferGraphics;
paint2D(g2d);
} catch (Exception e) {
//Debug.EngineLogError("Engine", "Failed to clear rect for frame buffer (Failed to draw frame) - Exception");
} finally {
bufferGraphics.dispose();
}
}
private void DrawBackBufferToScreen () {
bufferStrategy.show();
Toolkit.getDefaultToolkit().sync();
}
private void paint2D (Graphics2D g2d) {
// Multi-Used Variables
int canvasWidth = Math.round(screenWidth / 2);
int canvasHeight = Math.round(screenHeight / 2);
// Draw panel borders
// View2D
g2d.setColor(Color.black);
g2d.drawRect((canvasWidth) - (canvasWidth / 2) - 1, canvasHeight - (Math.round(canvasHeight / 1.35f)) - 1, canvasWidth + 1, canvasHeight + 1);
}
}
Any and all relevant answers are greatly appreciated.
EDIT: Fixed code to be able to be tested raw
There's a lot wrong in your code, but the biggest problem is here:
public void paint(Graphics g) {
// Something to go here
}
By overriding paint, you're preventing the JFrame from doing its necessary painting of itself, its borders, and relevant to your problem, its child components. So your menu never draws!
You should never draw directly in the JFrame, but if you absolutely must (and you don't), at least call the super's painting method:
public void paint(Graphics g) {
super.paint(g);
// Something to go here
}
Better still-- never override paint but instead draw inside a JPanel's paintComponent method (still calling the super's paintComponent method within) and display that JPanel within your JFrame.
Key links:
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
I'm not sure what the rest of your code is trying to do, but you've got big threading issues, other painting issues,... do read the tutorials to avoid guessing. Also you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
Related
I am quite new to Java and started learning on YouTube. To practice GUI Programs, I decided to make my own and am now trying to resize an image to add to a button in my aplication. I searched how to resize images and found some source code online which I decided to test and put in my own program, but when I call the method I get an unreported exception java.io.IOException; must be caught or declared to be thrown error and the IntelliJ IDE says Unhandled exception: java.io.IOException. I have the try-catch blocks in my code, but this still comes up. How can I fix this? Here is some of my code:
Images.java (class with the resizer method I found online) the try-catch I put in myself.
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Images {
//Image resizer method for scaling images
void resizeImage(String inputImagePath, String outputImagePath, int scaledWidth, int scaledHeight) throws IOException {
//reads input image
File inputFile = new File(inputImagePath);
BufferedImage inputImage = ImageIO.read(inputFile);
//creates output image
BufferedImage outputImage = new BufferedImagee(scaledWidth, scaledHeight, inputImage.getType());
//scales the inputImage to the output image
Graphics2D g2d = outputImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
// extracts extension of output file
String formatName = outputImagePath.substring(outputImagePath.lastIndexOf(".") + 1);
//writes to output file
ImageIO.write(outputImage, formatName, new File(outputImagePath));
try {
inputFile = null;
inputImage = ImageIO.read(inputFile);
}
catch(IOException e){
e.printStackTrace();
System.out.println("image file path is null");
}
}
}
GUI.java (where the error appears when I try to call the method). The error appears at plus.resizeImage.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import com.company.Images;
public class GUI extends JFrame {
//This will be used for dimensions of the window
private int height, width;
GUI(int w, int h) {
super("OS Control");
setWidth(w);
setHeight(h);
setSize(getWidth(), getHeight());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setContent();
setVisible(true);
}
//Gets and sets for height and width of window
public void setHeight(int height) {
this.height = height;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public int getWidth() {
return width;
}
////////////////////////////////////////////////
/*Method with the actual contents of the aplication
i.e buttons, text fields, etc.
*/
void setContent() {
//variables used in the methods for ease of changing if needed
int buttonWidth, buttonHeight;
int searchBarWidth, searchBarHeight;
buttonWidth = 200;
buttonHeight = 100;
searchBarWidth = 350;
searchBarHeight = 25;
//Panel for the two center buttons
JPanel buttons = new JPanel();
//flow layout to center horizontally
buttons.setLayout(new FlowLayout());
buttons.setBackground(Color.decode("#9E9E9E"));
JButton mechanicButton = new JButton("Mecanicos");
mechanicButton.setPreferredSize(new Dimension(buttonWidth, buttonHeight));
mechanicButton.setFocusable(false);
mechanicButton.addActionListener(new MechanicButtonEventHandling());
buttons.add(mechanicButton);
JButton osButton = new JButton("Ordens de Servico");
osButton.setPreferredSize(new Dimension(buttonWidth, buttonHeight));
osButton.setFocusable(false);
osButton.addActionListener(new OSButtonEventHandling());
buttons.add(osButton);
JPanel center = new JPanel();
//gridbag layout to center vertically
center.setLayout(new GridBagLayout());
center.setBackground(Color.decode("#9E9E9E"));
//combine the two to center horizontally and vertically
center.add(buttons);
JPanel search = new JPanel();
search.setLayout(new FlowLayout());
search.setBackground(Color.decode("#9E9E9E"));
search.setSize(new Dimension(getWidth(), searchBarHeight));
JTextField searchBar = new JTextField("Pesquisar: ");
searchBar.setPreferredSize(new Dimension(searchBarWidth, searchBarHeight));
searchBar.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 10));
search.add(searchBar);
JPanel plusPanel = new JPanel();
plusPanel.setLayout(new BorderLayout());
plusPanel.setSize(new Dimension(10, 10));
Images plus = new Images();
plus.resizeImage("plus.png","plusButton.png", 10, 10);
ImageIcon plusButtonImage = new ImageIcon("plusButton.png");
JButton plusButton = new JButton(plusButtonImage);
plusButton.setSize(new Dimension(10, 10));
plusPanel.add(plusButton, BorderLayout.SOUTH);
//add to jframe
add(search);
add(center);
add(plusPanel);
}
private class MechanicButtonEventHandling implements ActionListener {
public void actionPerformed(ActionEvent e) {
JFrame mechanicList = new JFrame("Lista de Mecanicos");
mechanicList.setSize(getWidth(), getHeight());
mechanicList.setLocation(100, 100);
mechanicList.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
mechanicList.setVisible(true);
}
}
private class OSButtonEventHandling implements ActionListener {
public void actionPerformed(ActionEvent e) {
JFrame osList = new JFrame("Lista de ordens de servico");
osList.setSize(getWidth(), getHeight());
osList.setLocation(700, 100);
osList.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
osList.setVisible(true);
}
}
}
You need to have a better look at how Java handles exceptions.
Your Images#resizeImage method contains a few operations that throw an IOException this being, the ImageIO#read and ImageIO#write calls.
At the bottom of the method's body you do this:
try {
inputFile = null;
inputImage = ImageIO.read(inputFile);
} catch(IOException e){
e.printStackTrace();
System.out.println("image file path is null");
}
In this code bit you're handling the thrown IOException with a try-catch clause. The
same cannot be said though for these calls:
BufferedImage inputImage = ImageIO.read(inputFile);
ImageIO.write(outputImage, formatName, new File(outputImagePath));
Since both of these thrown an exception which is not handled within the method's scope (i.e with a try-catch clause), you're forcing the method's signature to have a throws declaration for the IOException thrown by these two. Since, IOException is a checked exception, the compiler expects to find a try-catch clause wrapping the call to Images#resizeImage method.
To fix your code you have two possible solutions:
Remove the try-catch clause from the method's body, leaving only the throws declaration forcing callers to handle the exception at the calling point.
Wrap almost all of the method's body or the places where an IOException is thrown in try-catch clauses, thus handling the exception within the method's body (not a good idea since this way you'll not know whether the act of resizing failed or not).
It seems that your understanding of how exceptions work and how you need to handle them is a bit limited, so before doing anything else I would suggest to take a small detour and check on them.
https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
After writing and modifying this code, I encountered with this problem:
Clicking with the mouse is making the object appear for a secong and then fly out diagonally of the image bounds.
apparentally the function "repaint()" is responsible for this occurence in "paint(Graphics g)" block.
eliminating the reapaint() part make the object appear for a second and then dissappear.
public class MainWindow extends JFrame implements MouseListener
{
public BufferedImage myImage,packman_icon;
private ArrayList<Point> points;
public MainWindow()
{
initGUI();
this.addMouseListener(this);
}
private void initGUI()
{
MenuBar menuBar = new MenuBar();
Menu File = new Menu("File");
Menu Run=new Menu("Run");
Menu Insert=new Menu("Insert");
MenuItem New=new MenuItem("New");
MenuItem Open = new MenuItem("Open");
MenuItem Save=new MenuItem("Save");
MenuItem start=new MenuItem("start");
MenuItem stop=new MenuItem("stop");
MenuItem packman=new MenuItem("packman");
MenuItem fruit=new MenuItem("fruit");
menuBar.add(File);
menuBar.add(Run);
menuBar.add(Insert);
File.add(New);
File.add(Open);
File.add(Save);
Run.add(start);
Run.add(stop);
Insert.add(packman);
Insert.add(fruit);
this.setMenuBar(menuBar);
try {
myImage = ImageIO.read(new File("C:\\Users\\Owner\\Desktop\\Matala3\\Ariel1.png"));//change according to your path
packman_icon=ImageIO.read(new File("C:\\Users\\Owner\\Desktop\\pacman_icon.gif"));
} catch (IOException e) {
e.printStackTrace();
}
}
int x = -1;
int y = -1;
public void paint(Graphics g)
{
super.paintComponents(g);
g.drawImage(myImage, 0, 0, this);
g.drawImage(packman_icon, x, y, 20, 20, this);
if(x!=-1 && y!=-1)
{
int r = 10;
x = x - (r / 2);
y = y - (r / 2);
g.fillOval(x, y, r, r);
}
}
#Override
public void mouseClicked(MouseEvent arg) {
System.out.println("mouse Clicked");
System.out.println("("+ arg.getX() + "," + arg.getY() +")");
x = arg.getX();
y = arg.getY();
repaint();
}
}
public class Main
{
public static void main(String[] args)
{
MainWindow window = new MainWindow();
window.setVisible(true);
window.setSize(window.myImage.getWidth(),window.myImage.getHeight());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I want the image icon to stay in picture and not dissappear, thus creating multiple objects that appear on the picture.
**I edited the code acoording to instructions: deleted reapint()
method from paint and used
super.paintComponet(g)
but now it inly appears for a brief second and then dissappears.
Don't use AWT components in a Swing application. Swing component start with "J" (JMenuBar, JMenu, JMenuItem).
//public void paint(Graphics g)
protected void paintComponent(Graphics g)
The original comment was to override paintCompnent(...).
Also, painting is a dynamic process and the painting methods are invoked whenever Swing determines the components needs to be painted so you need to make sure to reset the state each time the component is painted.
Therefore, a painting method should NOT change the state of the class. You are using the x/y variables for two purposes:
to paint the image
to paint the oval.
Because you update the x/y variable in the painting method, this will affect the location of the image the next time the painting method is invoked.
If you want the image fixed then you need to use separate variables for the location of the image.
You will also need to reset the x/y variables in the painting method to paint the ovals, since these variables are local and need to be reset each time the painting is done.
I create this to draw a fish when the mouse is pressed at the mouse's x and y coordinate. but i seems then that the drawfish method is not being called. I can't find the reason why is it is not working. I would be me very grateful for any help.
/*FishTank*/
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
/*FishTank class-contains a frame and the WinstonCanvas.*/
public class FishTank{
public static void main ( String[] args ){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
public void run(){
JFrame window = new JFrame();
window.setTitle("Fish Tank");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 700, 430);
window.getContentPane().add(new FishTankCanvas());
window.setVisible(true);
}
});
}
}
/*FishTankCanvas is a component that allows drawing shapes.*/
class FishTankCanvas extends JComponent {
static Graphics2D g;
int x = 11;
Timer myTimer;
public FishTankCanvas(){
myTimer = new Timer (2, new ActionListener(){
public void actionPerformed (ActionEvent evt){
repaint();
}
});
myTimer.start();
}
public void paint(Graphics graphics) {
g = (Graphics2D)graphics;
//makes the background white
Color backgroundColor = new Color(89, 216, 255);//light blue
g.setColor(backgroundColor);
g.fillRect(0,0,this.getWidth(),this.getHeight());
// drawfish (Graphics graphics, int bodyX, int bodyY, int bodyLength,int bodyHeight, int tailwidth, int eyesize,int tailcolor, int bodycolor)
// Mouselistener and mouseadapter
this.addMouseListener (new MouseAdapter() {
public void mousePressed(MouseEvent e) {
//call drawfish method
drawfish(FishTankCanvas.g,e.getX(), e.getY(),118,74,1,((int) (Math.random()*(4 - 0))));
repaint();
}
});
// x coordinate plus 1 of fish (animate)
x= x + 1;
}
// drawfish method
public void drawfish(Graphics graphics, int bodyX, int bodyY, int bodyLength,int bodyHeight,int tailcolor, int bodycolor ){
Graphics2D g = (Graphics2D)graphics;
bodyX +=x;
//colours
Color[] colours= new Color[5];
colours[0] = new Color(0, 0, 0);//black
colours[1] = new Color(162, 0, 255);//purple
colours[2] = Color.red;//red
colours[3] = new Color(255,255,0);// yellow
colours[4] = new Color(60,179,113);//green
//draw fish
// body
g.setColor(colours[bodycolor]);
g.fillOval(bodyX, bodyY, bodyLength, bodyHeight);
// tail
g.setColor(colours[tailcolor]);
int tailWidth = bodyLength/4;
int tailHeight = bodyHeight/2;
int[] tailPointx = new int[3];
int[] tailPointy = new int[3];
tailPointx[0]=bodyX;
tailPointy[0]=bodyY+bodyHeight/2;
tailPointx[1]=bodyX-tailWidth;
tailPointy[1]=bodyY+bodyHeight/2-tailHeight;
tailPointx[2]=bodyX-tailWidth;
tailPointy[2]=bodyY+tailHeight+tailHeight;
g.fillPolygon(tailPointx, tailPointy, 3);
// eye
g.setColor(colours[0]);
g.fillOval(bodyX+3*bodyLength/4, bodyY+bodyHeight/2-bodyHeight/5, bodyHeight/5, bodyHeight/5);
}
}
i seems then that the drawfish method is not being called.
Well that is easy enough to verify. All you need to do is add debug code to the method to determine if this is true or not. Then you can tell us if that is the problem instead of guessing.
Other problems:
Don't add the MouseListener to the component in a painting method. The listener should be added in the constructor of your class.
Don't override paint(). Custom painting is done by overriding the paintComponent() method. And don't forget to invoke super.paintComponent(...).
Extend JPanel instead of JComponent. Then you can just use the setBackground() method to paint the background.
However, the real problem is that when you click the mouse the fish might get drawn, but then the Timer does a repaint which will clear the panel 2ms later, so you never really see the fish. Get rid of the Timer. There is no need for the Timer to draw a fish.
Assuming you want to paint multiple fish you need to keep track of every place you click and then paint all the fish. The two way of doing this are:
Keep an ArrayList of the points where you want to paint the fish and then iterate through this list in your painting method
Paint the fish on a BufferedImage when the mouse click happens, and then just paint the image.
See Custom Painting Approaches for working examples of both of these approaches.
I'm trying to create this basic photo editing app via java swing. I have my code to work somewhat for when 1 picture is imported; I have 3 views - photo view which displays the photo only, thumbnail view which should display thumbnails of the pictures and split view which should be a combination of photo in BorderLayout.CENTER and thumbnail in BorderLayout.SOUTH. I've put in images and code excerpts as to why this isn't working the way it should. I can't upload any images but hopefully the excerpts provide much detail.
Split View Related Excerpts:
public void changeMode(boolean p, boolean b, boolean s){
/*
* Photo View will display a single PhotoComponent2 in a large area.
*/
isPhoto = p;
if (isPhoto){
//have a child JPanel set as CENTER component of BorderLayout of the JScrollPane (scroll)
childPhoto = new JPanel();
childPhoto.add(displayPhotos.get(getCurrentPhoto()), BorderLayout.CENTER);
System.out.println("in lc photo view class");
}
/*
* Browser View will hold all the images.
*/
isBrowse = b;
if(isBrowse){
//have a child JPanel set as CENTER component of BorderLayout to hold grid of thumbnails within
// JScrollPanel (scroll)
this.removeAll();
childBrowse = new JPanel();
tc2 = new ThumbnailComponent(displayPhotos.get(getCurrentPhoto()));
childBrowse.setLayout(new WrapLayout());
childBrowse.add(tc2);
// for(int i = 0; i < displayThumbs.size(); i++){
// childBrowse.add(displayThumbs.get(i));
// System.out.println(displayThumbs.get(i));
// }
System.out.println("in lc browser view class");
}
/*
* Split View is a combination of Photo and Browser View in that the top half
* is Photo View and the bottom half is Browser View.
*/
isSplit = s;
if(isSplit){
//have a child JPanel in CENTER to hold PhotoComponent plus a child JPanel in SOUTH to hold thumbnails
containsAll = new JPanel();
containsAll.setLayout(new BorderLayout());
containsAll.add(childPhoto, BorderLayout.CENTER);
containsAll.add(childBrowse, BorderLayout.SOUTH);
System.out.println("in lc split view class");
}
}
This is basically all of my problems right now. Currently the thumbnails that are being created are based on the current image. If I go to photo view and and change the image being displayed with my forward/backward buttons and then go back to browser view I get the thumbnail of the respective image. However, I want to be able to create thumbnails for all images being imported and then display it. I tried the for loop (which I've commented out) and that didn't help either. The other code associated with this are my main class that creates the JFrame and the buttons,etc., the photoComponent that has my paintComponent method I use in my thumbnails and lightComponent classes.
MyPhotos3:
view = new JMenu("View");
mbar.add(view);
pv = new JRadioButton("Photo Viewer");
pv.addActionListener(new ActionListener(){ //change status
public void actionPerformed(ActionEvent e){
sbar.setText("Status: By clicking this, you'll be able to view your photos one at a time");
boolean p = true;
boolean b = false;
boolean s = false;
lc.changeMode(p,b,s);
scroll.add(lc.childPhoto);
scroll.setViewportView(lc.childPhoto);
scroll.getViewport().setBackground(Color.BLUE);
scroll.revalidate();
scroll.repaint();
}
});
b = new JRadioButton("Browser");
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){ //change status
sbar.setText("Status: By clicking this, you'll be able to view all your photos as thumbnails");
boolean p = false;
boolean b = true;
boolean s = false;
lc.changeMode(p,b,s);
scroll.setViewportView(lc.childBrowse);
scroll.getViewport().setBackground(Color.BLUE);
scroll.revalidate();
scroll.repaint();
}
});
sm = new JRadioButton("Split Mode");
sm.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){ //change status
sbar.setText("Status: By clicking this, you'll be able to view a single photo with a film strip dimensional view");
boolean p = false;
boolean b = false;
boolean s = true;
lc.changeMode(p,b,s);
scroll.setViewportView(lc.containsAll);
scroll.getViewport().setBackground(Color.BLUE);
scroll.revalidate();
scroll.repaint();
}
});
PhotoComponent:
public PhotoComponent2(boolean f, Image img){
isFlip = f;
init = img;
x = init.getWidth(null);
y = init.getHeight(null);
setPreferredSize(new Dimension (x,y));
bi = new BufferedImage(init.getWidth(null),init.getHeight(null),BufferedImage.TYPE_INT_ARGB);
newIcon = new ImageIcon(bi);
img1 = new JLabel("", newIcon, JLabel.CENTER);
image = img1;
this.add(img1);
this.addKeyListener(this);
this.setFocusable(true);
this.requestFocus(true);
//System.out.println("In constructor");
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(init, 0, 0, null);
this.addMouseListener(this);
this.addMouseMotionListener(this);
//System.out.println("In paintComponent");
Thumbnails:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.JComponent;
public class ThumbnailComponent extends JComponent{
/**
* ThumbnailComponent class is a way to create smaller versions of each photo passed in.
*
* #author Puja Sheth
* #version 1.0 10/16/2014
*/
private static final long serialVersionUID = 1L;
PhotoComponent2 pc;
Image img;
double x;
double y;
int newX;
int newY;
public ThumbnailComponent(PhotoComponent2 input){
pc = input;
img = pc.init;
x = (img.getWidth(null))/(.5);
y = (img.getHeight(null))/(.5);
newX = (int)x;
newY = (int)y;
setPreferredSize(new Dimension (newX,newY));
// add(input);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics gCopy = g.create();
Graphics2D g2d = (Graphics2D)gCopy;
g2d.scale(.5,.5);
pc.paintComponent(g2d);
}
}
Any help would be greatly appreciated!!!!
Won't solve your problem, but a few general comments about your code:
scroll.add(lc.childPhoto);
scroll.setViewportView(lc.childPhoto);
scroll.revalidate();
scroll.repaint();
You should never add a component to a scrollpane. The only line of code you need is:
scroll.setViewportView(lc.childPhoto);
The scrollpane will automatically revalidate() and repaint() itself when the viewport view is changed.
super.paintComponent(g);
g.drawImage(init, 0, 0, null);
this.addMouseListener(this);
this.addMouseMotionListener(this);
Never add listener to a component is a painting method. Painting methods are for painting only. A listener has nothing to do with painting. Also, the painting methods are invoked whenever Swing determines the component needs to be repainted so you will be adding multiple listeners to the component.
I've been taking AP Computer Science this year as a sophomore in high school and we mainly cover material like loops, classes, methods, general CS logic, and some math stuff. I am missing what I really loved about coding in the first place, making games. Now every game I have made had some sort of way to manage it whether it was using timers in visual basic or a XNA plugin for c# that setup a update method for me. The problem is I have not learned how to do this for java in my course. I've read up a little on threads and implements runnable but i'm not really sure where I'm going with it.
Class 1
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GFXScreen extends JFrame
{
/**
* #param screenHeigth
* #param screenHeigth
* #param The file name of the image. Make sure to include the extension type also
* #param The title at the top of the running screen
* #param The height of the screen
* #param The width of the screen
*/
public GFXScreen(String fileName, String screenTitle, int screenHeight, int screenWidth)
{
setLayout(new FlowLayout());
image1 = new ImageIcon(getClass().getResource(fileName));
label1 = new JLabel(image1);
this.add(label1);
//Set up JFrame
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setTitle(screenTitle);
this.setSize(screenWidth, screenHeight);
}
/**
* #param desired amount to move picture
*/
public void updatePic(int increment)
{
//update pos
label1.setBounds(label1.bounds().x, label1.bounds().y - increment,
label1.bounds().width, label1.bounds().height);
}
private ImageIcon image1;
private JLabel label1;
}
Class 2
public class MainClass implements Runnable {
public static void main(String[] args)
{
(new Thread(new MainClass())).start();
GFXScreen gfx = new GFXScreen("pixel_man.png", "pixel_Man", 1000, 1000);
}
public void run()
{
gfx.updatePic(1);
}
}
In this instance what I want to happen is, I want a picture that starts in the top to slowly move down smoothly to the bottom. How would i do this?
Suggestions:
Again, a Swing Timer works well for simple Swing animations or simple game loops. It may not be the greatest choice for complex or rigorous tame loops as its timing is not precise.
Most game loops will not be absolutely precise with time slices
And so your game model should take this into consideration and should note absolute time slices and use that information in its physics engine or animation.
If you must use background threading, do take care that most all Swing calls are made on the Swing event thread. To do otherwise will invite pernicious infrequent and difficult to debug program-ending exceptions. For more details on this, please read Concurrency in Swing.
I avoid using null layouts, except when animating components, as this will allow my animation engine to place the component absolutely.
When posting code here for us to test, it's best to avoid code that uses local images. Either have the code use an image easily available to all as a URL or create your own image in your code (see below for a simple example).
Your compiler should be complaining to you about your using deprecated methods, such as bounds(...), and more importantly, you should heed those complaints as they're there for a reason and suggest increased risk and danger if you use them. So don't use those methods, but instead check the Java API for better substitutes.
Just my own personal pet peeve -- please indicate that you've at least read our comments. No one likes putting effort and consideration into trying to help, only to be ignored. I almost didn't post this answer because of this.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class GfxPanel extends JPanel {
private static final int BI_WIDTH = 26;
private static final int BI_HEIGHT = BI_WIDTH;
private static final int GAP = 6;
private static final Point INITIAL_LOCATION = new Point(0, 0);
private static final int TIMER_DELAY = 40;
public static final int STEP = 1;
private ImageIcon image1;
private JLabel label1;
private Point labelLocation = INITIAL_LOCATION;
private int prefW;
private int prefH;
private Timer timer;
public GfxPanel(int width, int height) {
// the only time I use null layouts is for component animation.
setLayout(null);
this.prefW = width;
this.prefH = height;
// My program creates its image so you can run it without an image file
image1 = new ImageIcon(createMyImage());
label1 = new JLabel(image1);
label1.setSize(label1.getPreferredSize());
label1.setLocation(labelLocation);
this.add(label1);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
public void startAnimation() {
if (timer != null && timer.isRunning()) {
timer.stop();
}
labelLocation = INITIAL_LOCATION;
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
// My program creates its image so you can run it without an image file
private Image createMyImage() {
BufferedImage bi = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g2.setColor(Color.blue);
int x = GAP;
int y = x;
int width = BI_WIDTH - 2 * GAP;
int height = BI_HEIGHT - 2 * GAP;
g2.fillRect(x, y, width, height);
g2.dispose();
return bi;
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int x = labelLocation.x + STEP;
int y = labelLocation.y + STEP;
labelLocation = new Point(x, y);
label1.setLocation(labelLocation);
repaint();
if (x + BI_WIDTH > getWidth() || y + BI_HEIGHT > getHeight()) {
System.out.println("Stopping Timer");
((Timer) e.getSource()).stop();
}
}
}
private static void createAndShowGui() {
final GfxPanel gfxPanel = new GfxPanel(900, 750);
JButton button = new JButton(new AbstractAction("Animate") {
#Override
public void actionPerformed(ActionEvent arg0) {
gfxPanel.startAnimation();
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
JFrame frame = new JFrame("GFXScreen");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(gfxPanel);
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
What I always use is an infinite loop that calls an update method each iteration, in that method, you would do whatever was required to update the state of the game or render a GUI.
Example
public static void main(String[] args){
// Initialise game
while(true){
updateGame();
}
}
public static void updateGame(){
// Update things here.
}
What I also do ,which is a little more complex, is create and interface called IUpdateListener and have certain classes that are specialised for a certain element of the game. I would example have an InputListener, an AIListener, each handling a certain element of game updating.
public interface IUpdateListener{
public void update();
}
public class Main{
public static ArrayList<IUpdateListener> listeners = new ArrayList<IUpdateListener>();
public static void main(String[] args){
listeners.add(new InputListener());
while(true){
for(IUpdateListener listener : listeners){
listener.update();
}
}
}
}
public class InputListener implements IUpdateListener{
public void update(){
// Handle user input here etc
}
}