I have a JInternalFrame painted with a BufferedImage and contained in the JDesktopPane of a JFrame. I also have a JTextArea where I want to write some java code (function) that takes the current JInternalFrame's painted BufferedImage as an input and after doing some manipulation on this input it returns another manipulated BufferedImage that paints the JInternalFrame with new manipulated Image again.
Manipulation java code of JTextArea:-
public BufferedImage customOperation(BufferedImage CurrentInputImg)
{
Color colOld;
Color colNew;
BufferedImage manipulated=new BufferedImage(CurrentInputImg.getWidth(),CurrentInputImg.getHeight(),BufferedImage.TYPE_INT_ARGB);
// make all Red pixels of current image black
for(int i=0;i< CurrentInputImg.getWidth();i++) {
for(int j=0;j< CurrentInputImg.getHeight(),j++) {
colOld=new Color(CurrentInputImg.getRGB(i,j));
colNew=new Color(0,colOld.getGreen(),colOld.getBlue(),colOld.getAlpha());
manipulated.setRGB(i,j,colNew.getRGB());
}
}
return manipulated;
}
How can I run/compile this JTextArea java code at runtime and get a new
manipulated image for painting on JInternalFrame?
Here is my Main class:
(This class is not actual one but I have created it for you for basic interfacing containing JTextArea,JInternalFrame,Apply Button)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.JInternalFrame;
import javax.swing.JDesktopPane;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import java.io.File;
import java.util.*;
class MyCustomOperationSystem extends JFrame
{
public JInternalFrame ImageFrame;
public BufferedImage CurrenFrameImage;
public MyCustomOperationSystem() {
setTitle("My Custom Image Operations");
setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(), (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight());
JDesktopPane desktop=new JDesktopPane();
desktop.setPreferredSize(new Dimension((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(),(int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()));
try {
CurrenFrameImage=ImageIO.read(new File("c:/Lokesh.png"));
}catch(Exception exp) {
System.out.println("Error in Loading Image");
}
ImageFrame=new JInternalFrame("Image Frame",true,true,false,true);
ImageFrame.setMinimumSize(new Dimension(CurrenFrameImage.getWidth()+10,CurrenFrameImage.getHeight()+10));
ImageFrame.getContentPane().add(CreateImagePanel());
ImageFrame.setLayer(1);
ImageFrame.setLocation(100,100);
ImageFrame.setVisible(true);
desktop.setOpaque(true);
desktop.setBackground(Color.darkGray);
desktop.add(ImageFrame);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add("Center",desktop);
this.getContentPane().add("South",ControlPanel());
pack();
setVisible(true);
}
public JPanel CreateImagePanel() {
JPanel tempPanel=new JPanel() {
public void paintComponent(Graphics g) {
g.drawImage(CurrenFrameImage,0,0,this);
}
};
tempPanel.setPreferredSize(new Dimension(CurrenFrameImage.getWidth(),CurrenFrameImage.getHeight()));
return tempPanel;
}
public JPanel ControlPanel() {
JPanel controlPan=new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton customOP=new JButton("Custom Operation");
customOP.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evnt) {
JFrame CodeFrame=new JFrame("Write your Code Here");
JTextArea codeArea=new JTextArea("Your Java Code Here",100,70);
JScrollPane codeScrollPan=new JScrollPane(codeArea,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
CodeFrame.add(codeScrollPan);
CodeFrame.setVisible(true);
}
});
JButton Apply=new JButton("Apply Code");
Apply.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
// What should I do!!! Here!!!!!!!!!!!!!!!
}
});
controlPan.add(customOP);
controlPan.add(Apply);
return controlPan;
}
public static void main(String s[]) {
new MyCustomOperationSystem();
}
}
Note: in the above class JInternalFrame (ImageFrame) is not visible even though I have declared it visible. So, ImageFrame is not visible while compiling and running the above class. You have to identify this problem before running it.
Take a look at the Java 6 Compiler API
If you want to actually compile code from within java, it's doable but not trivial.
It's much better to use a scripting framework like Groovy--that would work great. Groovy is very java-compatible, it will almost always run java code directly (there are a few strange exceptions)
BeanShell is another scripting framework.
These both do just what you want without the effort of trying to figure out how to compile a class then load it into your existing runtime. (Actually, the problem I've seen isn't the initial compile, it's flushing your class so you can replace it with a new one after an edit).
Related
What I want to do:
I want to write a small application that can display an image. The user has to be able to zoom in and out of the image, move it around, and mark points on the image. Further down the line I want to analyze the points clicked, but I'm not there yet.
What I have so far:
In order to track down my problem I wrote a MVCE:
GUI class for handling the JFrame (and other UI elements later):
import javax.swing.*;
import java.net.MalformedURLException;
import java.net.URL;
public class MCVE_GUI {
public static void main(String[] args) throws MalformedURLException {
MCVE_ZoomPane zp = new MCVE_ZoomPane(new URL("https://fiji.sc/site/logo.png"));
JFrame f = new JFrame("PictureMeasurement");
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setContentPane(zp);
f.pack();
f.setLocationRelativeTo(null);
f.revalidate();
f.repaint();
f.setVisible(true);
}
}
ZoomPanel for handling the image and zooming:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
class MCVE_ZoomPane extends JPanel implements MouseMotionListener {
MCVE_ZoomPane(URL url){
JLabel image = new JLabel();
JScrollPane jsp = new JScrollPane(image);
//image.setIcon(new ImageIcon(url)); // picture, no input
//jsp.setPreferredSize(new Dimension(300,300)); //picture, no input
jsp.setPreferredSize(image.getPreferredSize()); //depends on position of image.setIcon
image.setIcon(new ImageIcon(url)); //no picture, input
this.add(jsp);
this.setPreferredSize(image.getPreferredSize());
this.addMouseMotionListener(this);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
}
public void mouseDragged(MouseEvent e) {
System.out.format("Dragged X:%d Y:%d\n",e.getX(), e.getY());
}
public void mouseMoved(MouseEvent e) {}
}
The problem:
Depending on where I put the image.setIcon(new ImageIcon(url)) I get either the image displayed or can listen to mouse clicks, but not both together. If I set the JScrollPane to a fixed preferred size without calling image.getPreferredSize() I always get a picture but no input.
Apparently I'm stupid. The JScrollPane/JLabel covered the JPanel which was the only component which had a MouseMotionListener. The solution is to add the single line of image.addMouseMotionListener(this);.
I thought about and tried different soltuions to this for at least three hours now. It's a hobby project, so no time constaints, but man do I feel stupid now.
I have a program that consists of four JButtons in a JFrame. I want to add images to the JButtons. The problem is that I can't seem to add them, despite trying multiple methods. When compiled, the output is input == null. The images are stored in the same folder as my .java files, so I can't figure out why they aren't showing up.
Main class:
import java.awt.GridLayout;
import java.awt.Image;
import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AutoProgram extends JFrame {
private static String[] files = {"workA","programmingA","leisureA","writingA"};
private static JButton[] bIcons = new JButton[4];
private static Image[] bImg = new Image[4];
public AutoProgram() {
super("Automation Project V.1");
JPanel autoIcons = new JPanel();
autoIcons.setLayout(new GridLayout(2,2));
// Initialize the four buttons (w/ images)
for(int i = 0; i < files.length; i++) {
bIcons[i] = new JButton();
try {
bImg[i] = ImageIO.read(getClass().getResource(files[i].toLowerCase() + ".png"));
bIcons[i].setIcon(new ImageIcon(bImg[i]));
} catch (Exception ex) {
System.out.println(ex);
}
autoIcons.add(bIcons[i]);
}
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));;
mainPanel.add(autoIcons);
add(mainPanel);
pack();
}}
Window class:
public class Window {
public static void main(String[] args) {
AutoProgram frame = new AutoProgram();
frame.setSize(315,315);
frame.setLocationRelativeTo(null);
frame.setFocusable(true);
frame.setResizable(true);
frame.setVisible(true);
}
}
Any help would be greatly appreciated. Thanks!
Before going into the answer to your question, please read the following recommendations:
private static JButton[] bIcons = new JButton[4]; Creating static fields could break your program, so be careful when to use them. Not really needed in this case, please read What does the 'static' keyword do in a class?
JFrame is a rigid container which cannot be placed inside others, and you're not changing it's functionallity anywhere in your program, so there's no need to call extends JFrame, it's better to create a JFrame instance then. See: Extends JFrame vs. creating it inside the program for more information about this.
You're correctly calling pack() but later in the code you're calling frame.setSize(315,315); which "destroys" the changes made by pack(), use one or the other, not both, I recommend you to leave pack() call.
You're not placing your program in the Event Dispatch Thread (EDT), you can fix it by changing your main(...) method as follows:
public static void main (String args[]) {
//Java 7 and below
SwingUtilities.invokeLater(new Runnable() {
//Your code here
});
//Java 8 and higher
SwingUtilities.invokeLater(() -> {
//Your code here
});
}
Now, let's go to the solution:
Your code works fine, I think that your errors might come from the following posibilities:
Calling files[i].toLowerCase() (.toLowerCase() method might be breaking your program, Java is case sensitive).
Your images are not PNG but JPG or JPEG (look at the extension carefully)
Your images are damaged
Good day everyone! I just got back into programming, and I'm facing some problem with the construction of my code. What I'm trying to do is a menu for a future application that could help me and my friends when we play a certain board game.
So right now, I'm having difficulty to figure out how I should structure my code. I have 3 class planned so far. the Main class, which create a JFrame. a MainFrame class which help the main setup the frame, and finally the third class is MainPanel, which display the proper JPanel on the frame depending on the state of the program.
The plan JPanel classes are:
a menu Panel, with 3 button on it: New, Load and Exit.
a loading Panel, which just display "Loading" while the application load stuff (will be use when someone click New)
a loadBoard Panel, which display the list of created board (when someone click Load)
I'm having 2 issue right now:
Where do I fit the code to monitor the Key event (such as KeyListener on the frame, so independently of where I am at in the program, the program Exit when I press the Esc key.)
How do I make sure the repaint() is handle properly? I have a problem where the Label "Loading" change location when I resize the window.
I know my code ain't construct ideally, that's why I'm posting this thread. I would like to better understand how to setup the code to have a similar result of what I have right now, but well construct.
This is my code:
MAIN Class
package test.project
import java.awt.Dimension;
public class Main
{
public static void main(String[] args)
{
Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
javax.swing.SwingUtilities.invokeLater(() ->
{
MainFrame theWindow = new MainFrame("Test",screenSize);
theWindow.setLocationRelativeTo(null);
theWindow.getContentPane().add(new MenuPanel(theWindow,theWindow.getSize()));
});
}
}
MAINFRAME Class
package test.project;
import java.awt.Dimension;
import javax.swing.JFrame;
public class MainFrame extends JFrame
{
#SuppressWarnings("LeakingThisInConstructor")
public MainFrame(String windowName, Dimension theSize)
{
setTitle(windowName);
setSize(theSize.width/2,theSize.height/2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
MAINPANEL Class
package test.project;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class MainPanel extends JPanel
{
JFrame theHolder;
public MainPanel(JFrame holder, Dimension theSize)
{
theHolder = holder;
setSize(theSize);
}
}
class MenuPanel extends MainPanel implements ActionListener
{
JButton newButton = new JButton("NEW");
JButton loadButton = new JButton("LOAD");
JButton exitButton = new JButton("EXIT");
#SuppressWarnings("LeakingThisInConstructor")
public MenuPanel(JFrame holder, Dimension theSize)
{
super(holder, theSize);
setLayout(new GridLayout(0,1));
SetButton(this);
setVisible(true);
theHolder.repaint();
}
private void SetButton(JPanel thePanel)
{
newButton.addActionListener(this);
loadButton.addActionListener(this);
exitButton.addActionListener(this);
thePanel.add(newButton);
thePanel.add(loadButton);
thePanel.add(exitButton);
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource().equals(newButton))
{
theHolder.getContentPane().remove(this);
theHolder.getContentPane().add(new LoadingPanel(theHolder,theHolder.getSize()));
theHolder.repaint();
}
if(e.getSource().equals(loadButton))
{
}
else if(e.getSource().equals(exitButton))
{
System.exit(0);
}
}
}
class LoadingPanel extends MainPanel
{
JLabel loadingLabel = new JLabel("LOADING");
#SuppressWarnings("LeakingThisInConstructor")
public LoadingPanel(JFrame holder, Dimension theSize)
{
super(holder, theSize);
setLayout(new GridLayout(0,1));
SetLabel(this);
setVisible(true);
theHolder.repaint();
}
private void SetLabel(JPanel thePanel)
{
thePanel.add(loadingLabel);
loadingLabel.setSize(thePanel.getSize());
loadingLabel.setHorizontalAlignment(SwingConstants.CENTER);
loadingLabel.setVerticalAlignment(SwingConstants.CENTER);
}
}
I am writing this code so that it will add JPanels and will change the background color when clicked. The code in the class that runs the JFrame class is:
import javax.swing.*;
public class project9Driver {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Project9 w=new Project9();
w.setVisible(true);
w.setSize(900, 900);
}
}
The Project9 class is:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Project9 extends JFrame implements MouseListener{
JPanel panes[]=new JPanel[64];
public void Project9(){
JFrame mainFrame=new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container mainBox=mainFrame.getContentPane();
mainBox.setLayout(new GridLayout(8,8));
mainBox.addMouseListener(this);
for(int i=0;i<=63;i++){
panes[i].setBackground(Color.WHITE);
mainBox.add(panes[i]);
}
}
public void paint(Graphics g){
super.paintComponents(g);
}
public void mouseClicked(MouseEvent e) {
for(int i=0;i<=64;i++){
if(e.getSource()==panes[i]){
Random xR=new Random();
Random yR=new Random();
Random zR=new Random();
int x=xR.nextInt(255),y=yR.nextInt(255),z=zR.nextInt(255);
panes[i].setBackground(new Color(x,y,z));
}
}
}
}
Whenever I try to run the program, it comes up with an empty GUI window. What am I missing?
Project9 is a Frame, and you're creating another Frame inside of Project9 and you're not showing it, and becouse of that, just Project9 (w) is draw on screen, but it doesn't have anything.
You have to use "this" instead of another frame.
public class Project9 extends JFrame implements MouseListener{
JPanel panes[]=new JPanel[64];
public void Project9(){
//JFrame mainFrame=new JFrame(); delete this.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container mainBox= this.getContentPane();
Three answer all point out different problems with your code.
You should start with a proper working example. The TopLevelDemo.java code from the Swing tutorial on Using Top Level Containers will show you the basics and the proper way to create GUI components.
You should not even be extending JFrame. It is important that all components are created on the Event Dispatch Thread which is why the invokeLater() code is used in the tutorial.
Use the tutorial for examples of using all Swing components. Other example will show you how to extend JPanel for a more complex GUI. You don't need to extend JFrame.
The original problem I noticed with the code is:
public void paint(Graphics g){
super.paintComponents(g);
}
Don't override the paint() method. There is no reason to do this!
The paint() method is for painting and you are not doing any custom painting.
First problem is this that you are using constructor Project9 w=new Project9();
and in class Project9 you are defining method public void Project9(){ you should remove void keyword.
public Project9(){
//JFrame mainFrame=new JFrame(); delete this.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container mainBox= this.getContentPane();
I am having problems displaying an image on a frame. When the picture is displayed the top left corner doesn't go to the (0,0) specified, also the background of the window takes on visual components of whatever was behind the window when I first ran it. Does anybody know what's wrong? Thanks in advance-
import java.awt.image.ImageObserver;
import java.io.File;
import javax.imageio.*;
import javax.swing.*;
public class Window extends JFrame{
//the pictures
Image testImage = null;
Image backPic = null;
//constructor
Window(){
super("window");
this.startWindow();
}
public void startWindow(){
Image customIcon = Toolkit.getDefaultToolkit().getImage("iconImage.gif");
testImage = Toolkit.getDefaultToolkit().getImage("tester.gif");
backPic = Toolkit.getDefaultToolkit().getImage("black.png");
setSize(700,600);
setIconImage(customIcon);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
}
public void paint(Graphics g){
g.drawImage(testImage,0,0,null);
}
}
The problem is that your testImage is not yet fully loaded when paint() is called. To fix this, you can invoke this instead:
g.drawImage(testImage,0,0,this);
But my preferred approach would be to use a JLabel and let it handle the image drawing. I also strongly recommend to not override JFrame.paint() (and if you do, at least call super.paint(g)). If you really want to draw an image yourself, extend JComponent and override paintComponent()
So my advice to you use JLabels for example to show Images, it's the simpliest way you can sure use. I created similar basic project that demonstate this way.
/**
* #author Sajmon
*/
package com.sajmon.window;
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Window extends JFrame {
private JLabel pictureLabel;
private Container controls;
public Window() {
super("window");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
this.setSize(300, 300);
this.startWindow();
}
private void startWindow() {
controls = new Container();
controls = getContentPane();
controls.setLayout(new FlowLayout());
pictureLabel = new JLabel(new ImageIcon("picture.png"));
controls.add(pictureLabel);
}
}
And Main method for run application.
/**
*
* #author Sajmon
*/
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Window w = new Window();
w.setVisible(true);
}
});
}
}
Note: If you working with Swing, you should starting your application with Runnable interface. This way is generally recommended.
Hope it helps.