Placing an image within a jmenubar + jtoolbar - java

I would like to know if it's possible to set an image as background for a jmenubar+jtoolbar (not only for one of theym, not one for each of theym But on for BOTH) ...
Anyone's got an idea ??
How should I do that if it's possible ?
Thanks !
Here an image to explain :
Solved :: I used two images (cutted to the right size to suite my jmenubar+jtoolbar) and added these to the object's declarations as overrides and it works great ! Here is a piece of code :
///////////////////////////////
JToolBar toolBar = new JToolBar(){
#Override
protected void paintComponent(Graphics g){
Image photo = getToolkit().getImage("src/MainFrame/Images/xtremeCalliBottom.png");
super.paintComponent(g) ;
int x=(mainFrame.getWidth()-200), y=0 ;
if(photo != null)
g.drawImage (photo, x, y, this);
}
};
// ............
//========== Menu Bar
jMenuBar = new JMenuBar(){
#Override
protected void paintComponent(Graphics g){
Image photo = getToolkit().getImage("src/MainFrame/Images/xtremeCalliTop.png");
super.paintComponent(g) ;
int x=(mainFrame.getWidth()-200), y=0 ;
if(photo != null)
g.drawImage (photo, x, y, this);
}
};
// ................
jMenuBar.setPreferredSize(new Dimension(100, 25));
toolBar.setPreferredSize(new Dimension(100,40));

Sure, but you'll have to override them separately. You'll also need to keep some global variable (or one that you can pass between the two) so that they can know how big each of them are.
You'll need to override paintComponent() or add your own UI delegate to do the painting. You can load the image and paint just the top portion (or relative percentage) on the menubar, then paint just the bottom portion or relative percentage on the toolbar.

Related

Java swing jbutton charging old image

i created a custom Java Button like this
public class GraphicPaintedButton extends JButton implements ToPaint{
protected BufferedImage background;
private boolean painted = false;
public GraphicPaintedButton() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(painted){
System.out.println("PAINTING!");
Dimension size = getSize();
g.drawImage(background, 0, 0,size.width, size.height,0, 0, background.getWidth(), background.getHeight(), null);
}
}
#Override
public void loadImage(String url){
painted = true;
URL imagePath = getClass().getResource(url);
BufferedImage result = null;
try {
result = ImageIO.read(imagePath);
} catch (IOException | IllegalArgumentException e) {
System.err.println("Errore, immagine non trovata");
e.printStackTrace();
}
background = result;
}
}
Iif i load an image on the button, it calls the repaint,and it's good, the image is shown, when i load a new Image, it calls the repaint again and the new Image is shown. The problem is when i pass the mouse over the button, it calls the rapaint, but loads the old image. Why? And how did it get the old image, as the new one should have replaced it?
I don't know why you want to go this extend and not simply use the icon property of the button, but...
First, I'd get rid of the painted flag, it runs the risk of allowing the paintComponent method to try and paint a null image, because the loadImage method may fail, but the painted flag is always set to true - Let's face it, you could easily end up with painted == true and background == null ... which is not a valid state
Instead, reason about the actual state you're interested in...
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Dimension size = getSize();
g.drawImage(background, 0, 0, size.width, size.height, 0, 0, background.getWidth(), background.getHeight(), null);
}
}
I would also change the loadImage method
public void loadImage(URL url) throws IOException {
background = ImageIO.read(url);
revalidate();
repaint();
}
First, don't use String, it's meaning is to ambiguous, instead, specify the lowest common parameter you're willing to deal with.
Secondly, the image is either going to load or it's not, if you're not going to deal with the exception, in any meaningful fashion, pass it back to the caller who may be in a better position to deal with it - IMHO
I don't know if this important or not, but I'd also consider overriding the getPreferredSize method...
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(10, 10) : new Dimension(background.getWidth(), background.getHeight());
}
This will at least try and match the button's size to the size of the image

Button not working when trying to draw a line

I'm new to Java and teaching myself and trying to build this program. It will create dots when the mouse clicks, but won't draw a line when the button is pushed. (eventually the line will connect the dots, but I'm not there yet.) First I just need to get it to draw something when pushed and work from there. I've tried multiple things and I can't get it to work. Here is my code:
public void init()
{
LineDrawListener listener = new LineDrawListener ();
addMouseListener (listener);
Button lineGraph = new Button("Graph Line");
lineGraph.addActionListener (this);
add (lineGraph, BorderLayout.EAST);
setBackground (Color.yellow);
setSize (APPLET_WIDTH, APPLET_HEIGHT);
}
public void paint(Graphics g)
{
// draws dots on screen
g.setColor(Color.blue);
if (current != null)
{
xcoordinates.addElement (current.x);
ycoordinates.addElement (current.y);
count++;
g.fillOval (current.x-4, current.y-4, 10, 10);
repaint();
}
if (push == true)
{
g.drawLine (5, 5, 30 , 30);
repaint();
}
}
class LineDrawListener extends MouseAdapter
{
public void mouseClicked (MouseEvent event)
{
current = event.getPoint();
repaint();
}
}
public void actionPerformed (ActionEvent event)
{
Object action = event.getSource();
if(action==lineGraph)
{
push = true;
}
}
Any help on how to get the button to work would be much appreciated. Thanks in advance.
The reason you can not get the line to draw is that repaint() posts a request to repaint the component. You are using it as if it refreshes the view somehow. You need to change three things in your code, all in paint():
Do not call repaint() in paint()
Override paintComponent() rather than paint() so your borders get drawn if you should ever have them at a later time.
Call super.paintComponent() in paintComponent() to do some initialization for you. It is probably OK not to for something this simple, but good practice for the future.
Here is what the code would look like:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// draws dots on screen
g.setColor(Color.blue);
if (current != null)
{
xcoordinates.addElement (current.x);
ycoordinates.addElement (current.y);
count++;
g.fillOval (current.x-4, current.y-4, 10, 10);
}
if (push == true)
{
g.drawLine (5, 5, 30 , 30);
}
}
Don't paint on top-level containers like JApplet
Rather paint on a JPanel and override the paintComponent method and call super.paintComponet(g)
#Override
protected void paintComponent(Graphic g){
super.paintComponent(g);
...
}
Don't call repaint() from inside the paint() method. Call it in your actionPerformed()
Learn to post an SSCCE
Number 3 is your most dire problem
Don't override paint(). Don't invoke repaint() in a painting method, this can cause in infinite loop.
Check out Custom Painting Approaches for working examples of the two common ways to do custom paintint:
by using a List to track the objects to be painted
by painting to a BufferedImage

How do I redraw things when my JFrame is restored (deiconified)?

I have a very basic little JFrame with JToggleButtons and subclassed JPanels that know how to draw what I want them to draw. Selecting a button causes an oval to appear in the corresponding panel. Unselecting the buttons makes the drawings disappear.
Unfortunately, minimizing (iconifying) and then restoring (deiconifying) causes any drawn shapes to disappear. So I need to trigger redrawings manually. The problem is that I can only get the redrawing done (that is, I only see it) if I show a message box first.
Here's the deiconify event for the JFrame:
private void formWindowDeiconified(java.awt.event.WindowEvent evt)
{
//having this message makes everything work
JOptionPane.showMessageDialog(null, "Useless message this is.");
//but if I skip it, I'm SOL
//what's going on?
drawAll();
}
This method goes over all of my buttons and asks for the redraws when necessary:
public void drawAll()
{
for (int i=0; i<channels; i++)
{
if (buttons[i].isSelected())
{
lightboxes[i].drawMe();
}
}
}
and here is my subclassed JPanel:
class MyJPanel extends JPanel {
public void drawMe()
{
Graphics myGraphics = this.getGraphics();
myGraphics.fillOval(0, 0, this.getWidth(), this.getHeight());
}
public void unDraw()
{
this.invalidate();
this.repaint();
}
}
The window should automatically be repainted once it is restored by the RepaintManager. The problem is you are not performing custom painting like you should...
This is not how to do custom painting...
public void drawMe()
{
Graphics myGraphics = this.getGraphics();
myGraphics.fillOval(0, 0, this.getWidth(), this.getHeight());
}
getGraphics can return null and is, at best, a snapshot of the graphics state.
Painting in Swing can occur at any time for many different reasons, most of which you don't have control over (nor should you care).
Your job is simply to respond to these repaint requests and update your components state.
Swing has a detailed paint chain which is called automatically and which you can use.
You should be overriding paintComponent and performing all painting within this method
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
Firstly, for speed I would use double buffering. It's best to paint your graphics off screen and display them to the screen when the drawing has completed. The below should sort you out.
public class MyPanel extends JPanel {
private BufferedImage buffer;
private Graphics2D canvas;
#Override
public void paintComponent(Graphics g) {
if(buffer == null) {
buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
canvas = buffer.createGraphics();
}
canvas.fillOval(0, 0, this.getWidth(), this.getHeight());
g.drawImage(buffer, 0, 0, this);
}
}
I'm just providing this answer so people can see what I ended up doing. The major lesson pointed out by everyone was to use the component's paintComponent. See the comments for issues that you might be experiencing yourself.
Edit: Updated to reflect comments from MadProgrammer.
//with help from Slihp and MadProgrammer on StackOverflow
//http://stackoverflow.com/q/17331986/1736461
class MyJPanel extends JPanel {
private boolean buttonSelected = false;
#Override
public void paintComponent(Graphics g) {
//make sure the background gets painted (wacky results otherwise)
super.paintComponent(g);
//now if the corresponding toggle button is on, plop on the circle
if (buttonSelected)
{
g.fillOval(0, 0, this.getWidth(), this.getHeight());
}
}
//an action listener for the button calls this
public void setButtonSelected(boolean buttonStateIn)
{
buttonSelected = buttonStateIn;
}
}
I subclassed the buttons too, so I can get its "ID" off of it from the event handler:
class MyJToggleButton extends JToggleButton
{
private int whoAmI;
public MyJToggleButton(int whoAmIn)
{
//the string given to the constructor becomes the button's label
//("1", "2", "3", etc..)
super(Integer.toString(whoAmIn + 1));
whoAmI = whoAmIn;
}
public int getWho()
{
return whoAmI;
}
}
The JFrame code that makes the buttons:
private void makeButtons(int howMany)
{
buttons = new MyJToggleButton[howMany];
for (int i=0; i<howMany; i++)
{
buttons[i] = new MyJToggleButton(i);
buttons[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
//find out which button this is
MyJToggleButton button = (MyJToggleButton) evt.getSource();
int which = button.getWho();
//send the button state to the corresponding lightbox
lightboxes[which].setButtonSelected(button.isSelected());
//trigger its redrawing
lightboxes[which].invalidate();
lightboxes[which].repaint();
}
});
this.add(buttons[i]);
}
}
And that's the only manual redrawing I have to do - resizing and reshowing and all those other fun things eventually hit up the paintComponent, and it just has to know if its button is pushed to know what to do. Super clean and just what I wanted.

My JComponent will only repaint() once I manually resize the window, how do I get it to work as it should?

I have tried my best to read around on the topic but I cannot find/understand how to apply the answers to my piece code (and those I have applied don't work)
I have used an example from "Ivor Horton's Beginning Java 2 JDK book" and it is the first time I'm using repaint() but it doesn't seem to work unless I resize the window. It tries to repaint but leaves the screen blank.
Here's the code please let me know if there is something I'm doing wrong.
public class CurveDrawings extends JFrame{
public CurveDrawings (String title){
setTitle(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pane = new CurvePane(); //Create pane containing curves
Container content = getContentPane(); //Get the content pane
//Add the pane containing the curves to the content pane for the applet
content.add(pane);
MouseHandler handler = new MouseHandler();
pane.addMouseListener(handler);
pane.addMouseMotionListener(handler);
}
//Class defining pane on which to draw
class CurvePane extends JComponent{
public CurvePane(){
quadCurve = new QuadCurve2D.Double(
startQ.x, startQ.y, control.x, control.y, endQ.x, endQ.y
);
cubicCurve = new CubicCurve2D.Double(
startC.x, startC.y, controlStart.x, controlStart.y,
controlEnd.x, controlEnd.y, endC.x, endC.y
);
}
}
class Marker{//not needed for my problem}
class MouseHandler extends MouseInputAdapter{
public void mousePressed(MouseEvent e){
if(ctrlQuad.contains(e.getX(),e.getY())){
selected = ctrlQuad;}
else if(ctrlCubic1.contains(e.getX(),e.getY())){
selected = ctrlCubic1;}
else if(ctrlCubic2.contains(e.getX(),e.getY())){
selected = ctrlCubic2;}
}
public void mouseReleased (MouseEvent e){
selected = null;
}
public void mouseDragged (MouseEvent e){
System.out.println("DRAGGED");
if(selected != null){
//Set the marker to current cursor position
selected.setLocation(e.getX(),e.getY());
pane.validate();
pane.repaint();
}
}
Marker selected = null;
}
public void paint (Graphics g){
Graphics2D g2D = (Graphics2D)g; //Get a 2D device context
//Code to draw each component
}
//Points for quadratic curve
//Points for cubic curve
//More unnecessary code}
Incase it is any help here's the 'Launcher' class for the application
Thanks in advance.
You will need to call
super.paint(g);
in your paint method in your CurveDrawings class to avail of the painting functionality already provided in the JFrame super class.
Note, the standard way of using custom painting in Swing is to use custom components that are based on javax.swing.JComponent that use and override paintComponent. This approach would leverage Swing's optimized painting model.
See: Performing Custom Painting

Java Swing - flickering Canvas graphics

I have to write a simple Java app which can load pictures, show it in a GUI form, allow the user to apply some transformation, and show the transformed picture.
My solution is working fine, but the UI is flickering a bit, because the repaint method called too often (for example when the user scaling the image with a JSlider)
My code looks like this:
public class ImageCanvas extends Canvas
{
private BufferedImage image;
// ...
#Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
if(image != null)
{
// I draw out the image...
}
}
public void setImage(BufferedImage image)
{
this.image = image;
this.repaint();
}
public void setRotation(double rotation)
{
this.rotation = rotation;
this.repaint();
}
public void setScale(double scaleX, double scaleY)
{
//set the scaling field, then repaint ....
}
// and so on...
}
And, of course, I have an ImageCanvas control on my main UI, and I simply call the public methods (see for example the "setRotation" method above) which repaint the canvas area. I know it's a simple question, but I don't even find a DoubleBuffered property on the Canvas...
Any help appreciated.
Double buffering is built-in for Swing (i.e. JComponent derived) classes.
If you want built-in double-buffering, you should extend JPanel rather than Canvas, and override paintComponent, not paint.
If you can use JPanel than go for it. Please make sure you are not overriding the JPanel.paint method, override JPanel.paintComponent instead.
See this link for details.
Usually graphic lags in these applications can be caused by setting a empty variable at the top of the script, then changing its value, then waiting for the repaint to update it. You could try changing the:
setRotation(double rotation);
so that it rotates the image in that method.
Just a general thing I happen to see while dealing with graphics.

Categories

Resources