I want to set the font size of button on componentResized event. I get the screensize and the size of the button. But can't get a way to calculate the preferred font size to set. If the Width of button is increased/decreased the font size also should increase/decrease accordingly. I can't get an object of Graphics also.
What could be a solution to work out for this problem ?
This is more of brute force solution.
1) You can try getting the font metrics using doing something like this:
// get metrics from the graphics
FontMetrics metrics = graphics.getFontMetrics(font);
// get the height of a line of text in this font and render context
int hgt = metrics.getHeight();
// get the advance of my text in this font and render context
int adv = metrics.stringWidth(text);
// calculate the size of a box to hold the text with some padding.
Dimension size = new Dimension(adv+2, hgt+2);
2) Then you can search through the fonts sizes that fit your component.
Font savedFont = oldFont;
for (int i = 0; i < 100; i++) {
Font newFont = new Font(oldFont.getFontName(), oldFont.getStyle(), i);
Dimension d = getFontSize(g,newFont,text);
if(componentSize.height < d.height || componentSize.width < d.width){
return savedFont;
}
savedFont = newFont;
}
Putting it all together (note this is not tested)
public Dimension getFontSize(Graphics graphics, Font font, String text){
// get metrics from the graphics
FontMetrics metrics = graphics.getFontMetrics(font);
// get the height of a line of text in this font and render context
int hgt = metrics.getHeight();
// get the advance of my text in this font and render context
int adv = metrics.stringWidth(text);
// calculate the size of a box to hold the text with some padding.
Dimension size = new Dimension(adv+2, hgt+2);
return size;
}
public Font findFont(Dimension componentSize, Font oldFont, String text, Graphics g){
//search up to 100
Font savedFont = oldFont;
for (int i = 0; i < 100; i++) {
Font newFont = new Font(oldFont.getFontName(), oldFont.getStyle(), i);
Dimension d = getFontSize(g,newFont,text);
if(componentSize.height < d.height || componentSize.width < d.width){
return savedFont;
}
savedFont = newFont;
}
return oldFont;
}
EDIT using component to get FontMetrics
public Dimension getFontSize(FontMetrics metrics ,Font font, String text){
// get the height of a line of text in this font and render context
int hgt = metrics.getHeight();
// get the advance of my text in this font and render context
int adv = metrics.stringWidth(text);
// calculate the size of a box to hold the text with some padding.
Dimension size = new Dimension(adv+2, hgt+2);
return size;
}
public Font findFont(Component component, Dimension componentSize, Font oldFont, String text){
//search up to 100
Font savedFont = oldFont;
for (int i = 0; i < 100; i++) {
Font newFont = new Font(oldFont.getFontName(), oldFont.getStyle(), i);
Dimension d = getFontSize(component.getFontMetrics(newFont),newFont,text);
if(componentSize.height < d.height || componentSize.width < d.width){
return savedFont;
}
savedFont = newFont;
}
return oldFont;
}
Measuring Text
If you would like the font size to adjust automagically on resizing, you could try something like this:
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public final class ButtonFrame extends JFrame {
ButtonFrame(String buttonText) {
final JButton button = new JButton(buttonText);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
float fittedFontSize = 1.0f;
while (getFittedText(button, fittedFontSize += 1.0f).equals(button.getText()));
button.setFont(button.getFont().deriveFont(fittedFontSize - 1.0f));
button.revalidate();
button.repaint();
}
});
getContentPane().add(button);
}
private String getFittedText(JButton button, float fontSize) {
Insets i = button.getInsets();
Rectangle viewRect = new Rectangle();
Rectangle textRect = new Rectangle();
Rectangle iconRect = new Rectangle();
viewRect.x = i.left;
viewRect.y = i.top;
viewRect.width = button.getWidth() - (i.right + viewRect.x);
viewRect.height = button.getHeight() - (i.bottom + viewRect.y);
textRect.x = textRect.y = textRect.width = textRect.height = 0;
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
return SwingUtilities.layoutCompoundLabel(
button,
button.getFontMetrics(button.getFont().deriveFont(fontSize)),
button.getText(),
button.getIcon(),
button.getVerticalAlignment(),
button.getHorizontalAlignment(),
button.getVerticalTextPosition(),
button.getHorizontalTextPosition(),
viewRect,
textRect,
iconRect,
button.getIconTextGap());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new ButtonFrame("sample text");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
});
}
}
You could create a class ResizingButton with a paintComponent which wraps the super.paintComponent. Then do on the (Graphics2D)graphics a resizing transformation. The reason: font resizing is stepwise.
If you delve deeper into resizing fonts, use a FontRenderingContext with fractional metrics.
In response to the comment some code:
public class ResizingButton extends JButton {
#Override
protected void paintComponent(Graphics g) {
int h = this.getHeight();
final int DEFAULT_H = 26;
double resizal = ((double)h) / DEFAULT_H;
String t = getText();
setText("<html><span style='font-size:" + (resizal*11) + "'>" + t);
super.paintComponent(g);
setText(t);
}
I found that the above (Java 6/7) works. Graphics2D.scale also scales border and is hence too cumbersome.
Setting the text as in the last but one answer causes a high load on the CPU.
My proposal is to scale the font accordingly:
public class ScalableJButton extends JButton {
int mCurrentSize = 0;
Font mInitialFont = null;
int mInitialHeight;
private static final long serialVersionUID = 1L;
public ScalableJButton(String pString) {
super(pString);
init();
}
public ScalableJButton() {
super();
init();
}
private void init() {
mInitialFont = getFont();
}
#Override
protected void paintComponent(Graphics g) {
if (mInitialHeight == 0) {
mInitialHeight = getHeight();
}
int resizal = this.getHeight() * mInitialFont.getSize() / mInitialHeight;
if(resizal != mCurrentSize){
setFont(mInitialFont.deriveFont((float) resizal));
mCurrentSize = resizal;
}
super.paintComponent(g);
}
}
Related
How can I implement Marquee effect in Java Swing
Here's an example using javax.swing.Timer.
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
/** #see http://stackoverflow.com/questions/3617326 */
public class MarqueeTest {
private void display() {
JFrame f = new JFrame("MarqueeTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String s = "Tomorrow, and tomorrow, and tomorrow, "
+ "creeps in this petty pace from day to day, "
+ "to the last syllable of recorded time; ... "
+ "It is a tale told by an idiot, full of "
+ "sound and fury signifying nothing.";
MarqueePanel mp = new MarqueePanel(s, 32);
f.add(mp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
mp.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MarqueeTest().display();
}
});
}
}
/** Side-scroll n characters of s. */
class MarqueePanel extends JPanel implements ActionListener {
private static final int RATE = 12;
private final Timer timer = new Timer(1000 / RATE, this);
private final JLabel label = new JLabel();
private final String s;
private final int n;
private int index;
public MarqueePanel(String s, int n) {
if (s == null || n < 1) {
throw new IllegalArgumentException("Null string or n < 1");
}
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
sb.append(' ');
}
this.s = sb + s + sb;
this.n = n;
label.setFont(new Font("Serif", Font.ITALIC, 36));
label.setText(sb.toString());
this.add(label);
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
#Override
public void actionPerformed(ActionEvent e) {
index++;
if (index > s.length() - n) {
index = 0;
}
label.setText(s.substring(index, index + n));
}
}
I know this is a late answer, but I just saw another question about a marquee that was closed because it was considered a duplicate of this answer.
So I thought I'd add my suggestion which takes a approach different from the other answers suggested here.
The MarqueePanel scrolls components on a panel not just text. So this allows you to take full advantage of any Swing component. A simple marquee can be used by adding a JLabel with text. A fancier marquee might use a JLabel with HTML so you can use different fonts and color for the text. You can even add a second component with an image.
Basic answer is you draw your text / graphic into a bitmap and then implement a component that paints the bitmap offset by some amount. Usually marquees / tickers scroll left so the offset increases which means the bitmap is painted at -offset. Your component runs a timer that fires periodically, incrementing the offset and invalidating itself so it repaints.
Things like wrapping are a little more complex to deal with but fairly straightforward. If the offset exceeds the bitmap width you reset it back to 0. If the offset + component width > bitmap width you paint the remainder of the component starting from the beginning of the bitmap.
The key to a decent ticker is to make the scrolling as smooth and as flicker free as possible. Therefore it may be necessary to consider double buffering the result, first painting the scrolling bit into a bitmap and then rendering that in one go rather than painting straight into the screen.
Here is some code that I threw together to get you started. I normally would take the ActionListener code and put that in some sort of MarqueeController class to keep this logic separate from the panel, but that's a different question about organizing the MVC architecture, and in a simple enough class like this it may not be so important.
There are also various animation libraries that would help you do this, but I don't normally like to include libraries into projects only to solve one problem like this.
public class MarqueePanel extends JPanel {
private JLabel textLabel;
private int panelLocation;
private ActionListener taskPerformer;
private boolean isRunning = false;
public static final int FRAMES_PER_SECOND = 24;
public static final int MOVEMENT_PER_FRAME = 5;
/**
* Class constructor creates a marquee panel.
*/
public MarqueePanel() {
this.setLayout(null);
this.textLabel = new JLabel("Scrolling Text Here");
this.panelLocation = 0;
this.taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
MarqueePanel.this.tickAnimation();
}
}
}
/**
* Starts the animation.
*/
public void start() {
this.isRunning = true;
this.tickAnimation();
}
/**
* Stops the animation.
*/
public void stop() {
this.isRunning = false;
}
/**
* Moves the label one frame to the left. If it's out of display range, move it back
* to the right, out of display range.
*/
private void tickAnimation() {
this.panelLocation -= MarqueePanel.MOVEMENT_PER_FRAME;
if (this.panelLocation < this.textLabel.getWidth())
this.panelLocaton = this.getWidth();
this.textLabel.setLocation(this.panelLocation, 0);
this.repaint();
if (this.isRunning) {
Timer t = new Timer(1000 / MarqueePanel.FRAMES_PER_SECOND, this.taskPerformer);
t.setRepeats(false);
t.start();
}
}
}
Add a JLabel to your frame or panel.
ScrollText s= new ScrollText("ello Everyone.");
jLabel3.add(s);
public class ScrollText extends JComponent {
private BufferedImage image;
private Dimension imageSize;
private volatile int currOffset;
private Thread internalThread;
private volatile boolean noStopRequested;
public ScrollText(String text) {
currOffset = 0;
buildImage(text);
setMinimumSize(imageSize);
setPreferredSize(imageSize);
setMaximumSize(imageSize);
setSize(imageSize);
noStopRequested = true;
Runnable r = new Runnable() {
public void run() {
try {
runWork();
} catch (Exception x) {
x.printStackTrace();
}
}
};
internalThread = new Thread(r, "ScrollText");
internalThread.start();
}
private void buildImage(String text) {
RenderingHints renderHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
renderHints.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
BufferedImage scratchImage = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_RGB);
Graphics2D scratchG2 = scratchImage.createGraphics();
scratchG2.setRenderingHints(renderHints);
Font font = new Font("Serif", Font.BOLD | Font.ITALIC, 24);
FontRenderContext frc = scratchG2.getFontRenderContext();
TextLayout tl = new TextLayout(text, font, frc);
Rectangle2D textBounds = tl.getBounds();
int textWidth = (int) Math.ceil(textBounds.getWidth());
int textHeight = (int) Math.ceil(textBounds.getHeight());
int horizontalPad = 600;
int verticalPad = 10;
imageSize = new Dimension(textWidth + horizontalPad, textHeight
+ verticalPad);
image = new BufferedImage(imageSize.width, imageSize.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
g2.setRenderingHints(renderHints);
int baselineOffset = (verticalPad / 2) - ((int) textBounds.getY());
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, imageSize.width, imageSize.height);
g2.setColor(Color.GREEN);
tl.draw(g2, 0, baselineOffset);
// Free-up resources right away, but keep "image" for
// animation.
scratchG2.dispose();
scratchImage.flush();
g2.dispose();
}
public void paint(Graphics g) {
// Make sure to clip the edges, regardless of curr size
g.setClip(0, 0, imageSize.width, imageSize.height);
int localOffset = currOffset; // in case it changes
g.drawImage(image, -localOffset, 0, this);
g.drawImage(image, imageSize.width - localOffset, 0, this);
// draw outline
g.setColor(Color.black);
g.drawRect(0, 0, imageSize.width - 1, imageSize.height - 1);
}
private void runWork() {
while (noStopRequested) {
try {
Thread.sleep(10); // 10 frames per second
// adjust the scroll position
currOffset = (currOffset + 1) % imageSize.width;
// signal the event thread to call paint()
repaint();
} catch (InterruptedException x) {
Thread.currentThread().interrupt();
}
}
}
public void stopRequest() {
noStopRequested = false;
internalThread.interrupt();
}
public boolean isAlive() {
return internalThread.isAlive();
}
}
This is supposed to be an improvement of #camickr MarqueePanel. Please see above.
To map mouse events to the specific components added to MarqueePanel
Override add(Component comp) of MarqueePanel in order to direct all mouse events of the components
An issue here is what do do with the MouseEvents fired from the individual components.
My approach is to remove the mouse listeners form the components added and let the MarqueePanel redirect the event to the correct component.
In my case these components are supposed to be links.
#Override
public Component add(Component comp) {
comp = super.add(comp);
if(comp instanceof MouseListener)
comp.removeMouseListener((MouseListener)comp);
comp.addMouseListener(this);
return comp;
}
Then map the component x to a MarqueePanel x and finally the correct component
#Override
public void mouseClicked(MouseEvent e)
{
Component source = (Component)e.getSource();
int x = source.getX() + e.getX();
int y = source.getY();
MarqueePanel2 marqueePanel = (MarqueePanel2) ((JComponent)e.getSource()).getParent();
double x2 = marqueePanel.getWidth();
double x1 = Math.abs(marqueePanel.scrollOffset);
if(x >= x1 && x <= x2)
{
System.out.println("Bang " + x1);
Component componentAt = getComponentAt(x+marqueePanel.scrollOffset, y);
if(comp instanceof MouseListener)
((MouseListener) componentAt).mouseClicked(e);
System.out.println(componentAt.getName());
}
else
{
return;
}
//System.out.println(x);
}
In this image you can see a default Java Swing color chooser, JColorChooser:
What I want is just the color square and vertical slider as outlined in red:
I was able to remove all the tabs (Swatches, HSL, etc) and the preview, but I was unable to remove all the sliders. How can I do this?
OK, just for grins, I decided to create your desired JPanel from scratch, wiring it up in a kind of View-Controller set up, since the model here is trivial -- a Color field within the controller. To use this component you create an instance of the component, add it to your GUI where desired and simply add a PropertyChangeListener to it that listens to its COLOR property:
hsvChooserPanel.addPropertyChangeListener(HsvChooserPanel.COLOR, pce -> {
Color c = (Color) pce.getNewValue();
// do what you want with Color value, c, here
});
The test class:
Version 2: this allows use of any 3 of the HSV panel/bar combinations, either the one with the bar focused on Hue, or Saturation, or Value (here Brightness). It uses an enum, ColorProperty, that has 3 values, ColorProperty.HUE, ColorProperty.SATURATION, and ColorProperty.BRIGHTNESS, and has the calculations within the enum items themselves on how to create the color bar and the color square BufferedImages. Comments welcome:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestHsvChooser2 {
// ***** choose which color panel / color bar you'd like to test:
// private static final ColorProperty COLOR_PROP = ColorProperty.HUE;
// private static final ColorProperty COLOR_PROP = ColorProperty.BRIGHTNESS;
private static final ColorProperty COLOR_PROP = ColorProperty.SATURATION;
private static void createAndShowGui() {
HsvChooserPanel2 hsvChooserPanel = new HsvChooserPanel2(COLOR_PROP);
JPanel testPanel = new JPanel();
JPanel outerPanel = new JPanel(new BorderLayout());
outerPanel.add(testPanel);
outerPanel.setBorder(BorderFactory.createTitledBorder("Test Panel"));
hsvChooserPanel.addPropertyChangeListener(HsvChooserPanel2.COLOR, pce -> {
Color c = (Color) pce.getNewValue();
testPanel.setBackground(c);
});
JPanel gridPanel = new JPanel(new GridLayout(0, 1, 10, 10));
gridPanel.add(hsvChooserPanel);
gridPanel.add(outerPanel);
JFrame frame = new JFrame("HSV Chooser");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(gridPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
The whole shebang:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.SwingPropertyChangeSupport;
#SuppressWarnings("serial")
public class HsvChooserPanel2 extends JPanel {
public static final String COLOR = "color";
private static final int PREF_W = 180;
private static final int PREF_H = PREF_W;
private static final int PREF_W_CB = 20;
private static final int GAP = 10;
private MyColorPanel2 colorPanel = null;
private MyColorBar2 colorBar = null;
private InnerControl2 innerControl = null;
public HsvChooserPanel2(ColorProperty colorProp) {
colorPanel = new MyColorPanel2(PREF_W, PREF_H, colorProp);
colorBar = new MyColorBar2(PREF_W_CB, PREF_H, colorProp);
innerControl = new InnerControl2(this, colorPanel, colorBar);
colorPanel.setColorPropertyValue(Color.RED); // !! magic value
setLayout(new BorderLayout(GAP, GAP));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
add(colorPanel, BorderLayout.CENTER);
add(colorBar, BorderLayout.LINE_END);
// propagate COLOR changes in the inner controller
// to this component's property change support
innerControl.addPropertyChangeListener(COLOR, pce -> {
firePropertyChange(COLOR, pce.getOldValue(), pce.getNewValue());
});
}
}
// listens for changes to both the color bar and the color panel
class InnerControl2 {
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private HsvChooserPanel2 hsvChooser;
private MyColorPanel2 colorPanel;
private MyColorBar2 colorBar;
private Color color; // This is all there is to the model, a "bound"
// property
public InnerControl2(HsvChooserPanel2 hsvChooser, MyColorPanel2 colorPanel, MyColorBar2 colorBar) {
this.hsvChooser = hsvChooser;
this.colorPanel = colorPanel;
this.colorBar = colorBar;
// listen for changes
colorPanel.addPropertyChangeListener(ColorPanelParent.CURSOR, new ColorPanelListener());
colorBar.addPropertyChangeListener(ColorPanelParent.CURSOR, new ColorBarListener());
}
public Color getColor() {
return color;
}
// classic setter method for a "bound" property
public void setColor(Color color) {
Color oldValue = this.color;
Color newValue = color;
this.color = color;
// notify listeners of the change
pcSupport.firePropertyChange(HsvChooserPanel2.COLOR, oldValue, newValue);
}
// allow outside classes the ability to listen
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
public HsvChooserPanel2 getHsvChooser() {
return hsvChooser;
}
// inner listeners
private class ColorPanelListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
Point p = colorPanel.getCursorP();
Color c = colorPanel.getColor(p);
colorBar.setColorPropertyValue(c);
setColor(c); // this will fire the prop change
// support
}
}
private class ColorBarListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// get hue from the color bar and use it to set the main hue
// of the color panel
Point p = colorBar.getCursorP();
Color c = colorBar.getColor(p);
colorPanel.setColorPropertyValue(c);
}
}
}
// parent of both color bar panel and color panel
#SuppressWarnings("serial")
abstract class ColorPanelParent extends JPanel {
public static final String CURSOR = "cursor";
private int prefW;
private int prefH;
private Point cursorP = new Point(0, 0);
private BufferedImage img = null;
private ColorProperty colorProperty;
private boolean panel;
public ColorPanelParent(int prefW, int prefH, ColorProperty colorProperty, boolean panel) {
this.prefW = prefW;
this.prefH = prefH;
this.colorProperty = colorProperty;
this.panel = panel;
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
public int getPrefH() {
return prefH;
}
public int getPrefW() {
return prefW;
}
public ColorProperty getColorProperty() {
return colorProperty;
}
public BufferedImage getImg() {
return img;
}
public Point getCursorP() {
return cursorP;
}
public void setImg(BufferedImage img) {
this.img = img;
repaint();
}
public Color getColor(Point p) {
Color c = null;
if (getImg() != null) {
int rgb = getImg().getRGB(p.x, p.y);
c = new Color(rgb);
}
return c;
}
// when the main hue is changed, we have to create a new
// background image to reflect the new main color
public void setColorPropertyValue(Color color) {
int w = getPrefW();
int h = getPrefH();
BufferedImage img = getColorProperty().createImage(color, w, h, panel);
setImg(img);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
// change the cursor point and then
// notify prop change support of changes
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
mouseResponse(e);
}
#Override
public void mouseDragged(MouseEvent e) {
mouseResponse(e);
}
private void mouseResponse(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (!contains(e.getPoint())) {
x = Math.max(0, x);
x = Math.min(prefW - 1, x);
y = Math.max(0, y);
y = Math.min(prefH - 1, y);
}
Point oldValue = cursorP;
cursorP = new Point(x, y);
firePropertyChange(CURSOR, oldValue, cursorP);
repaint();
}
}
}
// color bar on the right side of the HsvChooser JPanel.
// Controller action: Changing selection point on this JPanel
// will change the hue of the color panel
#SuppressWarnings("serial")
class MyColorBar2 extends ColorPanelParent {
public MyColorBar2(int prefW, int prefH, ColorProperty colorProperty) {
super(prefW, prefH, colorProperty, false);
// create and set the background image
setColorPropertyValue(Color.RED); // fix the magic number?
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // draws the background image
// this draws a line at the cursor's location
g.setXORMode(Color.WHITE);
int y = getCursorP().y;
g.drawLine(0, y, getPrefW(), y);
}
}
// color panel on the left side of the HsvChooser JPanel.
// Controller action: Changing selection point on this JPanel
// will notify listeners of a new COLOR selection
#SuppressWarnings("serial")
class MyColorPanel2 extends ColorPanelParent {
private static final int CURSOR_RADIUS = 8;
public MyColorPanel2(int prefW, int prefH, ColorProperty colorProperty) {
super(prefW, prefH, colorProperty, true);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // draws the background image
// draws the cross hatch indicating color selection point
g.setXORMode(Color.WHITE);
int x = getCursorP().x;
int y = getCursorP().y;
int x1 = x - CURSOR_RADIUS;
int y1 = y - CURSOR_RADIUS;
int x2 = x + CURSOR_RADIUS;
int y2 = y + CURSOR_RADIUS;
g.drawLine(x1, y, x2, y);
g.drawLine(x, y1, x, y2);
}
}
enum ColorProperty {
HUE {
#Override
public BufferedImage createImage(Color color, int w, int h, boolean panel) {
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
if (panel) {
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
// float array is HSB
float hue = Color.RGBtoHSB(red, green, blue, null)[0];
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float s = ((float) j) / (float) w;
float b = (h - (float) i) / (float) h;
int rgb = Color.getHSBColor(hue, s, b).getRGB();
img.setRGB(j, i, rgb);
}
}
} else {
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float hue = (h - (float) i) / (float) h;
int rgb = Color.getHSBColor(hue, 1f, 1f).getRGB();
img.setRGB(j, i, rgb);
}
}
}
return img;
}
},
SATURATION {
#Override
public BufferedImage createImage(Color color, int w, int h, boolean panel) {
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
// float array is HSB
float[] hsb = Color.RGBtoHSB(red, green, blue, null);
return panel ? createPanelImg(w, h, img, hsb) : createBarImg(w, h, img, hsb);
}
private BufferedImage createBarImg(int w, int h, BufferedImage img, float[] hsb) {
float hue = hsb[0];
// float brightness = hsb[2];
float brightness = 1f;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float saturation = (h - (float) i) / (float) h;
int rgb = Color.getHSBColor(hue, saturation, brightness).getRGB();
img.setRGB(j, i, rgb);
}
}
return img;
}
private BufferedImage createPanelImg(int w, int h, BufferedImage img, float[] hsb) {
float saturation = hsb[1];
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float hue = ((float) j) / (float) w;
float b = (h - (float) i) / (float) h;
int rgb = Color.getHSBColor(hue, saturation, b).getRGB();
img.setRGB(j, i, rgb);
}
}
return img;
}
},
BRIGHTNESS {
#Override
public BufferedImage createImage(Color color, int w, int h, boolean panel) {
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
// float array is HSB
float[] hsb = Color.RGBtoHSB(red, green, blue, null);
return panel ? createPanelImg(w, h, img, hsb) : createBarImg(w, h, img, hsb);
}
private BufferedImage createBarImg(int w, int h, BufferedImage img, float[] hsb) {
float hue = hsb[0];
// float saturation = hsb[1];
float saturation = 1f;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float brightness = (h - (float) i) / (float) h;
int rgb = Color.getHSBColor(hue, saturation, brightness).getRGB();
img.setRGB(j, i, rgb);
}
}
return img;
}
private BufferedImage createPanelImg(int w, int h, BufferedImage img, float[] hsb) {
float brightness = hsb[2];
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float hue = ((float) j) / (float) w;
float saturation = (h - (float) i) / (float) h;
int rgb = Color.getHSBColor(hue, saturation, brightness).getRGB();
img.setRGB(j, i, rgb);
}
}
return img;
}
};
public abstract BufferedImage createImage(Color color, int w, int h, boolean panel);
}
My solution:
colorChooser.setPreviewPanel(new JPanel());
AbstractColorChooserPanel[] panels = colorChooser.getChooserPanels();
for (AbstractColorChooserPanel accp : panels) {
if(!accp.getDisplayName().equals("HSV")) {
colorChooser.removeChooserPanel(accp);
}
}
JComponent current = (JComponent) colorChooser.getComponents()[0];
while( !current.getClass().toString().equals( "class javax.swing.colorchooser.ColorChooserPanel" ) ){
current = (JComponent) current.getComponents()[0];
}
for(Component jc : current.getComponents()){
if(!jc.getClass().toString().equals( "class javax.swing.colorchooser.DiagramComponent" )){
current.remove(jc);
}
}
This removes everything that I don't want, but I think making a custom one would be a better solution.
I am going to try trashgod's to see if it works better.
You can use the Swing Utils class to search for components of a given type on the panel.
In the example below you can find all the sliders and then make them invisible:
import java.awt.*;
import java.util.List;
import javax.swing.*;
import javax.swing.colorchooser.*;
public class ColorChooserPanel extends JPanel
{
ColorChooserPanel()
{
JColorChooser chooser = new JColorChooser();
AbstractColorChooserPanel[] panels = chooser.getChooserPanels();
for (AbstractColorChooserPanel panel: panels)
{
if ("HSL".equals(panel.getDisplayName()))
{
add( panel );
List<JSlider> sliders = SwingUtils.getDescendantsOfType(JSlider.class, panel, true);
for (JSlider slider: sliders)
{
slider.setVisible( false );
}
}
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("ColorChooserPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ColorChooserPanel());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
A look at the javax.swing.colorchooser internals reveals that ColorChooserComponentFactory creates subclasses of AbstractColorChooserPanel using ColorChooserPanel and a suitable subclass of ColorModel. ColorChooserPanel holds the parts you want as two instances of DiagramComponent: the left is named diagram and the right is named slider.
Instead of removing components from an existing ColorChooserPanel, consider Creating a Custom Chooser Panel that contains just the desired elements.
class MyChooserPanel extends AbstractColorChooserPanel implements PropertyChangeListener {
private final ColorModel model;
private final DiagramComponent diagram;
private final DiagramComponent slider;
MyChooserPanel(ColorModel model) {
this.model = model;
this.diagram = new DiagramComponent(this.panel, true);
this.slider = new DiagramComponent(this.panel, false);
}
…
}
Naturally, you'll have to recapitulate some of the (package-)private code, but the result will be less fragile.
i try to make a simple java game . ıt work fine but i draw a background but i didn't stop square's color , it always change
i write another class for that and i call it in main but i didn't work it
#SuppressWarnings("serial")
class BackPan extends JFrame{
private JLayeredPane layers;
private JPanel down;
static int width = Board.boardWidth;
static int height = Board.boardHeight;
Random rnd = new Random();
public BackPan(){
layers = new JLayeredPane();
rnd =new Random();
down = new JPanel(){
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D)g;
//***************************************************************
int low = 50;
int high = 255;
for(int i = 0; i<= width; i+=50){
g2d.setColor(new Color(rnd.nextInt(high-low)+low,rnd.nextInt(high-low)+low,rnd.nextInt(high-low)+low));
g2d.fillRect(i, 50, 50, 50);
for(int j = 0; j<= height; j += 50 ){
g2d.setColor(new Color(rnd.nextInt(high-low)+low,rnd.nextInt(high-low)+low,rnd.nextInt(high-low)+low));
g2d.fillRect(i, j, 50, 50);
}
}
}
};
//****************************************************************
down.setBounds(0, 0, width, height);
layers.add(down, new Integer(1));
getContentPane().add(layers, BorderLayout.CENTER);
}
}
Better than using a set seed for your randomization, simply fix the random image by one of two ways:
Create an array of colors that you randomize when needed and then use this array when drawing the background
Even better, simply draw your random colors to a BufferedImage and draw that in the paintComponent method. If this needs to be re-randomized, then re-create the image.
For an example of the latter, note that the image re-randomizes only when the button is pressed (by calling the createBackground() method):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class ColorSquares extends JPanel {
public static final int SQR_SIDE = 50;
public static final int COLUMNS = 20;
public static final int ROWS = 16;
private int columns;
private int rows;
private int sqrSide;
private Image backgroundImg;
public ColorSquares(int columns, int rows, int sqrSide) {
this.columns = columns;
this.rows = rows;
this.sqrSide = sqrSide;
backgroundImg = createBackground();
add(new JButton(new AbstractAction("New Background") {
#Override
public void actionPerformed(ActionEvent arg0) {
backgroundImg = createBackground();
repaint();
}
}));
}
public Image createBackground() {
int w = columns * sqrSide;
int h = rows * sqrSide;
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
float hue = (float) Math.random();
float saturation = (float) (Math.random() * 0.5 + 0.5);
float brightness = (float) (Math.random() * 0.5 + 0.5);
Color randColor = Color.getHSBColor(hue, saturation, brightness);
g.setColor(randColor);
int x = c * sqrSide;
int y = r * sqrSide;
g.fillRect(x, y, sqrSide, sqrSide);
}
}
g.dispose();
return img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(columns * sqrSide, rows * sqrSide);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Colors");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ColorSquares(COLUMNS, ROWS, SQR_SIDE));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
An additional benefit of using a BufferedImage is that it's quicker to draw this than as you're doing it.
The simplest solution would be to remember a constant random seed and set it via rnd.setSeed() each time paintComponent is called. For example:
private final static int SEED = 1000;
rnd.setSeed(SEED);
in my application I have label which has a font size over 200. This label contains big up and down (irregular)gap. How can I remove it ?
This is my code:
package Core;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class LabelDemo extends JPanel {
public LabelDemo() {
super(new GridBagLayout());
JLabel label2;
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
// Create the other labels.
label2 = new JLabel("Text-Only Label");
label2.setBorder(BorderFactory.createTitledBorder("aaaaaaaa"));
label2.setFont(new Font("Verdana", Font.PLAIN, (int) 220));
// label2.setBorder(new EmptyBorder(-50, 0, 0, 0));
// Add the labels.
add(label2, c);
}
/**
* Create the GUI and show it. For thread safety, this method should be invoked from the event dispatch thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("LabelDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add content to the window.
frame.add(new LabelDemo());
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event dispatch thread:
// creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
I also try my last post: How to change gap in swing label and experiment with insets but this looks different in linux and windows
Is there some better way how to remove this gap ?
JDigit may give you some ideas:
It override's paintComponent() to down-sample a high-resolution BufferedImage and control the geometry.
It uses setBorderPainted(false) to set the borderPainted property.
It uses a FocusHandler for custom highlighting.
Addendum: As noted here, the underlying problem is the font's leading, defined in FontMetrics as being included in the font's height. As suggested in a comment by #Guillaume Polet, you can render the text wherever you want in your own JComponent. TextLayout, discussed here, can be used to calculate the bounds, as shown below.
Pros:
Absolute control over placement.
Geometry of TexteLayout bounds based on FontMetrics.
Cons:
No Icon support.
No HTML support.
Note that the JComponent authors "recommend that you put the component in a JPanel and set the border on the JPanel."
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/16014525/230513
*/
public class UnleadedTest {
private static class Unleaded extends JComponent {
private Font font = new Font("Verdana", Font.PLAIN, 144);
private FontRenderContext frc = new FontRenderContext(null, true, true);
private String text;
private TextLayout layout;
private Rectangle r;
public Unleaded(String text) {
this.text = text;
calcBounds();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(r.width, r.height);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
calcBounds();
layout.draw(g2d, -r.x, -r.y);
}
private void calcBounds() {
layout = new TextLayout(text, font, frc);
r = layout.getPixelBounds(null, 0, 0);
}
}
private void display() {
JFrame f = new JFrame("Unleaded");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Unleaded label = new Unleaded("Unleaded");
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder("Title"));
panel.add(label);
f.add(panel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new UnleadedTest().display();
}
});
}
}
The "right way" to do this would be to extend "BasicLabelUI" and override the "protected String layoutCL()" method. This is the method that is responsible for laying out everything inside the label and is called when the "getPreferredSize()" of the JLabel is called. So this method determines the height the component is going to be.
If you drill down deep enough you'll see that the height is determined by the following line in the SwingUtilities:1021 class (which is used by layoutCL):
textR.height = fm.getHeight();
So the label is not causing the white space, the font is. The label just conforms to what the FontMetrics object says is the maximum height of the font for that size.
The easiest way would probably be to cheat; Force the size calculation to do something it shouldn't. Below is your example with a custom LabelUI component which you can experiment on. For example if you force the variable to 'dy' to '-40' the text will be at the top. If you want to make something more durable you could check all the leters in the string of the label, measure their maximum height and use that in the layoutCL method. But thats more work obviously.
package Core;
import sun.swing.SwingUtilities2;
import javax.swing.*;
import javax.swing.plaf.LabelUI;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.text.View;
import java.awt.*;
public class LabelDemo extends JPanel {
public LabelDemo() {
super(new GridBagLayout());
JLabel label2;
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
// Create the other labels.
label2 = new JLabel("Text-Only Label");
label2.setVerticalAlignment(SwingUtilities.TOP);
label2.setVerticalTextPosition(SwingUtilities.TOP);
label2.setUI(SkinnyLabelUI.createUI(label2));
label2.setBorder(BorderFactory.createTitledBorder("aaaaaaaa"));
label2.setFont(new Font("Verdana", Font.PLAIN, (int) 220));
// label2.setBorder(new EmptyBorder(-50, 0, 0, 0));
// Add the labels.
add(label2, c);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event dispatch thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("LabelDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add content to the window.
frame.add(new LabelDemo());
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event dispatch thread:
// creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
private static class SkinnyLabelUI extends BasicLabelUI {
private static final SkinnyLabelUI labelUI = new SkinnyLabelUI();
public static LabelUI createUI(JComponent c) {
return labelUI;
}
protected String layoutCL(
JLabel label,
FontMetrics fm,
String text,
Icon icon,
Rectangle viewR,
Rectangle iconR,
Rectangle textR) {
int verticalAlignment = label.getVerticalAlignment();
int horizontalAlignment = label.getHorizontalAlignment();
int verticalTextPosition = label.getVerticalTextPosition();
int horizontalTextPosition = label.getHorizontalTextPosition();
if (icon != null) {
iconR.width = icon.getIconWidth();
iconR.height = icon.getIconHeight();
} else {
iconR.width = iconR.height = 0;
}
/* Initialize the text bounds rectangle textR. If a null
* or and empty String was specified we substitute "" here
* and use 0,0,0,0 for textR.
*/
boolean textIsEmpty = (text == null) || text.equals("");
int lsb = 0;
int rsb = 0;
/* Unless both text and icon are non-null, we effectively ignore
* the value of textIconGap.
*/
int gap;
View v;
if (textIsEmpty) {
textR.width = textR.height = 0;
text = "";
gap = 0;
} else {
int availTextWidth;
gap = (icon == null) ? 0 : label.getIconTextGap();
if (horizontalTextPosition == SwingUtilities.CENTER) {
availTextWidth = viewR.width;
} else {
availTextWidth = viewR.width - (iconR.width + gap);
}
v = (label != null) ? (View) label.getClientProperty("html") : null;
if (v != null) {
textR.width = Math.min(availTextWidth,
(int) v.getPreferredSpan(View.X_AXIS));
textR.height = (int) v.getPreferredSpan(View.Y_AXIS);
} else {
textR.width = SwingUtilities2.stringWidth(label, fm, text);
lsb = SwingUtilities2.getLeftSideBearing(label, fm, text);
if (lsb < 0) {
// If lsb is negative, add it to the width and later
// adjust the x location. This gives more space than is
// actually needed.
// This is done like this for two reasons:
// 1. If we set the width to the actual bounds all
// callers would have to account for negative lsb
// (pref size calculations ONLY look at width of
// textR)
// 2. You can do a drawString at the returned location
// and the text won't be clipped.
textR.width -= lsb;
}
if (textR.width > availTextWidth) {
text = SwingUtilities2.clipString(label, fm, text,
availTextWidth);
textR.width = SwingUtilities2.stringWidth(label, fm, text);
}
textR.height = fm.getHeight();
System.out.println("font height: " + textR.height);
}
}
/* Compute textR.x,y given the verticalTextPosition and
* horizontalTextPosition properties
*/
if (verticalTextPosition == SwingUtilities.TOP) {
if (horizontalTextPosition != SwingUtilities.CENTER) {
textR.y = 0;
} else {
textR.y = -(textR.height + gap);
}
} else if (verticalTextPosition == SwingUtilities.CENTER) {
textR.y = (iconR.height / 2) - (textR.height / 2);
} else { // (verticalTextPosition == BOTTOM)
if (horizontalTextPosition != SwingUtilities.CENTER) {
textR.y = iconR.height - textR.height;
} else {
textR.y = (iconR.height + gap);
}
}
if (horizontalTextPosition == SwingUtilities.LEFT) {
textR.x = -(textR.width + gap);
} else if (horizontalTextPosition == SwingUtilities.CENTER) {
textR.x = (iconR.width / 2) - (textR.width / 2);
} else { // (horizontalTextPosition == RIGHT)
textR.x = (iconR.width + gap);
}
// WARNING: DefaultTreeCellEditor uses a shortened version of
// this algorithm to position it's Icon. If you change how this
// is calculated, be sure and update DefaultTreeCellEditor too.
/* labelR is the rectangle that contains iconR and textR.
* Move it to its proper position given the labelAlignment
* properties.
*
* To avoid actually allocating a Rectangle, Rectangle.union
* has been inlined below.
*/
int labelR_x = Math.min(iconR.x, textR.x);
int labelR_width = Math.max(iconR.x + iconR.width,
textR.x + textR.width) - labelR_x;
int labelR_y = Math.min(iconR.y, textR.y);
int labelR_height = Math.max(iconR.y + iconR.height,
textR.y + textR.height) - labelR_y;
int dx, dy;
if (verticalAlignment == SwingUtilities.TOP) {
dy = viewR.y - labelR_y;
} else if (verticalAlignment == SwingUtilities.CENTER) {
dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2));
} else { // (verticalAlignment == BOTTOM)
dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
}
if (horizontalAlignment == SwingUtilities.LEFT) {
dx = viewR.x - labelR_x;
} else if (horizontalAlignment == SwingUtilities.RIGHT) {
dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
} else { // (horizontalAlignment == CENTER)
dx = (viewR.x + (viewR.width / 2))
- (labelR_x + (labelR_width / 2));
}
/* Translate textR and glypyR by dx,dy.
*/
textR.x += dx;
textR.y += dy;
iconR.x += dx;
iconR.y += dy;
if (lsb < 0) {
// lsb is negative. Shift the x location so that the text is
// visually drawn at the right location.
textR.x -= lsb;
textR.width += lsb;
}
if (rsb > 0) {
textR.width -= rsb;
}
return text;
}
}
}
changing the border offset might help:
int OFFSET_TOP=50,OFFSET_BOTTOM=50;
label.setBorder(new TitledBorder(TITLE){
#Override
public Insets getBorderInsets(Component c, Insets insets){
return new Insets(insets.top - OFFSET_TOP, insets.left, insets.bottom - OFFSET_BOTTOM, insets.right);
}
});
I have displayed an image(ball) inside the JApplet, now I want the image to move in a vertical way (up and down). The problem is I don't know how to do it.
Could someone has an idea about this matter?
You need to set the position of that image to some calculated value (means you caculate the vertical position using time, speed and maybe other restrictions).
How you'd set that position depends on how you draw the image.
Example, based on drawing in the applet's (or a nested component's) paint(Graphics g) method:
//first calculate the y-position
int yPos += timeSinceLastPaint * speed; //increment the position
if( (speed > 0 && yPos > someMaxY) || (speed < 0 && yPos <0 ) ) {
speed *= -1; //if the position has reached the bottom (max y) or the top invert the direction
}
//in your paint(Graphics g) method:
g.drawImage(image, yPos, x, null);
Then you'd have to constantly repaint the applet.
More information on animations in applets can be found here: http://download.oracle.com/javase/tutorial/uiswing/components/applet.html
another example for javax.swing.Timer with moving Ojbects created by paintComponent(Graphics g), and I have lots of Start, not some blurred Mikado :-)
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class AnimationBackground {
private Random random = new Random();
private JFrame frame = new JFrame("Animation Background");
private final MyJPanel panel = new MyJPanel();
private JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER);
private JPanel stopPanel = new JPanel();
private JPanel startPanel = new JPanel();
public AnimationBackground() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
panel.setBackground(Color.BLACK);
for (int i = 0; i < 50; i++) {
Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155)));
star.setxIncr(-3 + random.nextInt(7));
star.setyIncr(-3 + random.nextInt(7));
panel.add(star);
}
panel.setLayout(new GridLayout(10, 1));
label.setForeground(Color.WHITE);
panel.add(label);
stopPanel.setOpaque(false);
stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.stopAnimation();
}
}));
panel.add(stopPanel);
startPanel.setOpaque(false);
startPanel.add(new JButton(new AbstractAction("Start moving...") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.startAnimation();
}
}));
panel.add(startPanel);
frame.add(panel);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AnimationBackground aBg = new AnimationBackground();
}
});
}
private class Star extends Polygon {
private static final long serialVersionUID = 1L;
private Point location = null;
private Color color = Color.YELLOW;
private int xIncr, yIncr;
static final int WIDTH = 500, HEIGHT = 500;
Star(Point location) {
int x = location.x;
int y = location.y;
this.location = location;
this.addPoint(x, y + 8);
this.addPoint(x + 8, y + 8);
this.addPoint(x + 11, y);
this.addPoint(x + 14, y + 8);
this.addPoint(x + 22, y + 8);
this.addPoint(x + 17, y + 12);
this.addPoint(x + 21, y + 20);
this.addPoint(x + 11, y + 14);
this.addPoint(x + 3, y + 20);
this.addPoint(x + 6, y + 12);
}
public void setColor(Color color) {
this.color = color;
}
public void move() {
if (location.x < 0 || location.x > WIDTH) {
xIncr = -xIncr;
}
if (location.y < 0 || location.y > WIDTH) {
yIncr = -yIncr;
}
translate(xIncr, yIncr);
location.setLocation(location.x + xIncr, location.y + yIncr);
}
public void setxIncr(int xIncr) {
this.xIncr = xIncr;
}
public void setyIncr(int yIncr) {
this.yIncr = yIncr;
}
public Color getColor() {
return color;
}
}
private class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Star> stars = new ArrayList<Star>();
private Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Star star : stars) {
star.move();
}
repaint();
}
});
public void stopAnimation() {
if (timer.isRunning()) {
timer.stop();
}
}
public void startAnimation() {
if (!timer.isRunning()) {
timer.start();
}
}
#Override
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
MyJPanel() {
this.setPreferredSize(new Dimension(512, 512));
}
public void add(Star star) {
stars.add(star);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Star star : stars) {
g.setColor(star.getColor());
g.fillPolygon(star);
}
}
}
}
How to move the image inside the JApplet ..?
Pretty much exactly the same way you might do it in a JFrame, JComponent or JPanel or...
Or to put that another way, nothing to do with applets and everything to do with Graphics2D. For more details, see the 2D Graphics Trail of the Java Tutorial.
When you've figured how to move an image and paint it to a Graphics2D, implement that logic in a JComponent or JPanel's paintComponent(Graphics) method and drop the component with moving image into a JApplet or JFrame (or a JPanel etc.).
For the animation side of it, use a javax.swing.Timer as seen in this example. This example does not extend any component. Instead, it creates a BufferedImage and adds it to a JLabel that is displayed to the user. When the timer fires, the code grabs the Graphics object of the image, and proceeds from there to draw the bouncing lines.
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
class LineAnimator {
public static void main(String[] args) {
final int w = 640;
final int h = 480;
final RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
hints.put(
RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY
);
final BufferedImage bi = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);
final JLabel l = new JLabel(new ImageIcon(bi));
final BouncingLine[] lines = new BouncingLine[100];
int factor = 1;
for (int ii=0; ii<lines.length; ii++) {
lines[ii] = new BouncingLine(w*factor,h*factor);
}
final Font font = new Font("Arial", Font.BOLD, 30);
ActionListener al = new ActionListener() {
int count = 0;
long lastTime;
String fps = "";
private final BasicStroke stroke = new BasicStroke(6);
public void actionPerformed(ActionEvent ae) {
count++;
Graphics2D g = bi.createGraphics();
g.setRenderingHints(hints);
g.setColor(new Color(55,12,59));
g.fillRect(0,0,w,h);
g.setStroke(stroke);
for (int ii=0; ii<lines.length; ii++) {
lines[ii].move();
lines[ii].paint(g);
}
if ( System.currentTimeMillis()-lastTime>1000 ) {
lastTime = System.currentTimeMillis();
fps = count + " FPS";
count = 0;
}
g.setColor(Color.YELLOW);
g.setFont(font);
g.drawString(fps,5,h-5);
l.repaint();
g.dispose();
}
};
Timer timer = new Timer(25,al);
timer.start();
JOptionPane.showMessageDialog(null, l);
//System.exit(0);
timer.stop();
}
}
class BouncingLine {
private final Color color;
private static final Random random = new Random();
Line2D line;
int w;
int h;
int x1;
int y1;
int x2;
int y2;
BouncingLine(int w, int h) {
line = new Line2D.Double(random.nextInt(w),random.nextInt(h),random.nextInt(w),random.nextInt(h));
this.w = w;
this.h = h;
this.color = new Color(
random.nextInt(255)
,random.nextInt(255)
,random.nextInt(255)
,64+random.nextInt(128)
);
x1 = (random.nextBoolean() ? 1 : -1);
y1 = (random.nextBoolean() ? 1 : -1);
x2 = -x1;
y2 = -y1;
}
public void move() {
int tx1 = 0;
if (line.getX1()+x1>0 && line.getX1()+x1<w) {
tx1 = (int)line.getX1()+x1;
} else {
x1 = -x1;
tx1 = (int)line.getX1()+x1;
}
int ty1 = 0;
if (line.getY1()+y1>0 && line.getY1()+y1<h) {
ty1 = (int)line.getY1()+y1;
} else {
y1 = -y1;
ty1 = (int)line.getY1()+y1;
}
int tx2 = 0;
if (line.getX2()+x2>0 && line.getX2()+x2<w) {
tx2 = (int)line.getX2()+x2;
} else {
x2 = -x2;
tx2 = (int)line.getX2()+x2;
}
int ty2 = 0;
if (line.getY2()+y2>0 && line.getY2()+y2<h) {
ty2 = (int)line.getY2()+y2;
} else {
y2 = -y2;
ty2 = (int)line.getY2()+y2;
}
line.setLine(tx1,ty1,tx2,ty2);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(color);
//line.set
g2.draw(line);
}
}
Update 1
I want to do it in JApplet(1) using the image(2), is it possible(3)?
The examples by mKorbel and myself feature either an image in a JLabel or custom rendering in a JPanel. In our case, we added the components to a JOptionPane & a JFrame. Either example could be just as easily added to a JApplet, or a JDialog, or as part of another panel, or.. See the Laying Out Components Within a Container lesson & Using Top-Level Containers in the Java Tutorial for more details.
Instead of the stars or lines in our examples, ..paint your image. My example goes so far as to demonstrate how to get the position to bounce around within the bounds of the container.
Sure it is possible, but "Batteries not included". Our intention is to give you some ideas that you can then adapt to your bouncing ball applet. I doubt anyone is going to create an example for you, using balls, in an applet. Though if you post an SSCCE that shows your intent and what you tried, I (and others) would often run with that source. If you want more specific answers, ask a more specific SSCCE. ;)
I want to do it in JApplet.
Why not both? You can have a hybrid application/applet as shown in this animation.