Da yoshi darauf hingewiesen wird, füllt der JLabel
den gesamten Inhaltsbereich aus, sodass das Klicken auf eine beliebige Stelle im Inhaltsbereich zu Mausereignissen für das Label führt.
Einige Wörter:
1) Sie auch GridBagLayout
, statt FlowLayout
, falls Sie die JLabel
in ihrer Mutterkomponente (sowohl vertikal als auch horizontal) zentriert nutzen könnten. Diese Lösung ist here.
Wie so:
final JPanel singleCenteredComponentJPanel = new JPanel(new GridBagLayout());
singleCenteredComponentJPanel.add(label);
frame.add(singleCenteredComponentJPanel);
2) Wenn darüber hinaus möchten Sie Mausklicks auf alle transparente Pixel des Etiketts Symbol (falls vorhanden) Sie können Sie wie folgt ignorieren:
Verwenden Sie die BufferedImage.getRGB(int x, int y)
, BufferedImage.getColorModel()
und ColorModel.getAlpha(int pixel)
Methoden, um den Alpha-Wert des angeklickten Pixels für jedes Mausereignis zu bestimmen. Wenn der Alpha-Wert gleich 0 ist, ist das Pixel vollständig transparent, ansonsten liegt der Alpha-Wert zwischen 1 und 255 (beide inklusive), was wiederum bedeutet, dass das Pixel nicht vollständig transparent ist. Beispielcode folgt unten.
Und statt Image.getScaledInstance(...)
das Bild zu skalieren (die Image
zurückkommt, aber wir brauchen BufferedImage
), verwenden Sie die Lösung here zur Verfügung gestellt.
Wie so:
private static void loadImage() throws IOException {
int newWidth = 80;
int newHeight = 40;
bi = ImageIO.read(RoundedButtonDemo.class.getResource("/resources/login.png"));
bi = getScaledBufferedImage(bi, newWidth, newHeight);
}
public static BufferedImage getScaledBufferedImage(final Image img,
final int newWidth,
final int newHeight) {
final GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice gdev = genv.getDefaultScreenDevice();
final GraphicsConfiguration gcnf = gdev.getDefaultConfiguration();
final BufferedImage simg = gcnf.createCompatibleImage(newWidth, newHeight, Transparency.TRANSLUCENT);
//Painting input image to output image:
final Graphics2D g2d = simg.createGraphics();
g2d.drawImage(img, 0, 0, newWidth, newHeight, null); //@Docs "...is scaled if necessary.".
g2d.dispose();
return simg;
}
Auch die Referenz ändern bi
von Image
zu BufferedImage
.
Und dann die MouseListener
des Etiketts:
private int count = 0;
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == label) {
//Get the mouse click position (in pixels),
//relative to the top-left corner of label:
final Point relativeClickPoint = e.getPoint();
//Obtain alpha value from the TYPE_INT_ARGB pixel:
final int pixel = bi.getRGB(relativeClickPoint.x, relativeClickPoint.y);
final int alpha = bi.getColorModel().getAlpha(pixel);
if (alpha > 0) { //Check if the pixel is not transparent.
if (count % 2 == 0) {
label.setText("Bye");
} else {
label.setText("Hello World");
}
count++;
}
}
}
Beachten Sie für die obige Umsetzung: Alle transparente Pixel des Bildes (einschließlich transparente Pixel „innerhalb“ der Form, falls vorhanden) außer Acht gelassen werden . Dies bedeutet, dass der Benutzer in die Mitte des Bildes klicken könnte und nichts passieren würde, wenn das angeklickte Pixel vollständig transparent wäre. Ich habe also angenommen, dass dies bei deinem Bild hier nicht der Fall ist.
3) Für die Skalierung der Image
, können Sie die neue Größe der Methode bestimmen collapseInside(...)
:
/**
* @param resultDim Output dimension (same aspect ratio as the original dimension, and inside containerDim).
* @param originalDim Original dimension.
* @param containerDim Dimension with the maximum width and maximum height.
*/
public static void collapseInside(final Dimension resultDim,
final Dimension originalDim,
final Dimension containerDim) {
resultDim.setSize(originalDim);
if (resultDim.width > containerDim.width) {
//Adjusting height for max width:
resultDim.height = (resultDim.height * containerDim.width)/resultDim.width;
resultDim.width = containerDim.width;
}
if (resultDim.height > containerDim.height) {
//Adjusting width for max height:
resultDim.width = (resultDim.width * containerDim.height)/resultDim.height;
resultDim.height = containerDim.height;
}
}
Mit dieser Methode:
a) Scaled Image
‚s Breite ist kleiner als oder gleich zur Behältergrößenbreite (resultDim.width <= containerDim.width
).
b) Gleiche Höhe (resultDim.height <= containerDim.height
).
c) Das Seitenverhältnis der ursprünglichen Image
Größe wird in der neuen Image
Größe beibehalten (resultDim.width/resultDim.height == originalDim.width/originalDim.height).
Mit Image.getScaledInstance(...)
und dem vorherigen getScaledBufferedImage(...)
könnte sich das Seitenverhältnis des Image
ändern.
So bearbeite ich die getScaledBufferedImage(...)
collapseInside(...)
zu verwenden:
public static BufferedImage getScaledBufferedImage(final Image img,
final int newWidth,
final int newHeight) {
final Dimension originalDim = new Dimension(img.getWidth(null), img.getHeight(null)),
containerDim = new Dimension(newWidth, newHeight),
resultDim = new Dimension();
collapseInside(resultDim, originalDim, containerDim);
final GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice gdev = genv.getDefaultScreenDevice();
final GraphicsConfiguration gcnf = gdev.getDefaultConfiguration();
final BufferedImage simg = gcnf.createCompatibleImage(resultDim.width, resultDim.height, Transparency.TRANSLUCENT);
//Painting input image to output image:
final Graphics2D g2d = simg.createGraphics();
g2d.drawImage(img, 0, 0, resultDim.width, resultDim.height, null); //@Docs "...is scaled if necessary.".
g2d.dispose();
return simg;
}
komplette Code für alle drei oben:
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public final class RoundedButtonDemo {
private static BufferedImage bi;
public static void main(String[] args) {
try {
loadImage();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
} catch (IOException e) {
// handle exception
}
}
private static void loadImage() throws IOException {
int newWidth = 80;
int newHeight = 40;
bi = ImageIO.read(RoundedButtonDemo.class.getResource("/resources/login.png"));
bi = getScaledBufferedImage(bi, newWidth, newHeight);
}
public static BufferedImage getScaledBufferedImage(final Image img,
final int newWidth,
final int newHeight) {
final Dimension originalDim = new Dimension(img.getWidth(null), img.getHeight(null)),
containerDim = new Dimension(newWidth, newHeight),
resultDim = new Dimension();
collapseInside(resultDim, originalDim, containerDim);
final GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice gdev = genv.getDefaultScreenDevice();
final GraphicsConfiguration gcnf = gdev.getDefaultConfiguration();
final BufferedImage simg = gcnf.createCompatibleImage(resultDim.width, resultDim.height, Transparency.TRANSLUCENT);
//Painting input image to output image:
final Graphics2D g2d = simg.createGraphics();
g2d.drawImage(img, 0, 0, resultDim.width, resultDim.height, null); //@Docs "...is scaled if necessary.".
g2d.dispose();
return simg;
}
/**
* @param resultDim Output dimension (same aspect ratio as the original dimension, and inside containerDim).
* @param originalDim Original dimension.
* @param containerDim Dimension with the maximum width and maximum height.
*/
public static void collapseInside(final Dimension resultDim,
final Dimension originalDim,
final Dimension containerDim) {
resultDim.setSize(originalDim);
if (resultDim.width > containerDim.width) {
//Adjusting height for max width:
resultDim.height = (resultDim.height * containerDim.width)/resultDim.width;
resultDim.width = containerDim.width;
}
if (resultDim.height > containerDim.height) {
//Adjusting width for max height:
resultDim.width = (resultDim.width * containerDim.height)/resultDim.height;
resultDim.height = containerDim.height;
}
}
private static void createAndShowGUI() {
final JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel label = new JLabel();
label.setSize(new Dimension(5, 5));
label.setIcon(new ImageIcon(bi));
label.setText("Hello World");
label.setHorizontalTextPosition(JLabel.CENTER);
// label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
label.addMouseListener(new MouseListener() {
private int count = 0;
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == label) {
//Get the mouse click position (in pixels),
//relative to the top-left corner of label:
final Point relativeClickPoint = e.getPoint();
//Obtain alpha value from the TYPE_INT_ARGB pixel:
final int pixel = bi.getRGB(relativeClickPoint.x, relativeClickPoint.y);
final int alpha = bi.getColorModel().getAlpha(pixel);
if (alpha > 0) { //Check if the pixel is not transparent.
if (count % 2 == 0) {
label.setText("Bye");
} else {
label.setText("Hello World");
}
count++;
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
});
final JPanel singleCenteredComponentJPanel = new JPanel(new GridBagLayout());
singleCenteredComponentJPanel.add(label);
frame.add(singleCenteredComponentJPanel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Alternativ können Sie auch die paintComponent(...)
von JPanel
und Graphics.drawImage(...)
verwenden außer Kraft setzen kann die Image
bi
zu malen an die JPanel
wie folgt:
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
//Drawing the image:
g.drawImage(img, 0, 0, null);
//Drawing the text:
//For centering the text, I used code from:
//https://stackoverflow.com/questions/27706197/how-can-i-center-graphics-drawstring-in-java
final FontMetrics metrics = g.getFontMetrics(g.getFont());
final int x = (img.getWidth(null) - metrics.stringWidth(text))/2;
final int y = (img.getHeight(null) - metrics.getHeight())/2 + metrics.getAscent();
g.drawString(text, x, y);
}
Wo img
ist bi
und text
ist der Text der Schaltfläche (d. H. "Hallo Welt" und "Tschüss").
Dann fügen Sie die MouseListener
zu der JPanel
wie sie ist.
komplette Code für diese (als „RoundedButtonDemo1
“ Klasse, in der gleichen Paket):
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public final class RoundedButtonDemo1 {
private static BufferedImage bi;
public static void main(String[] args) {
try {
loadImage();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
} catch (IOException e) {
// handle exception
}
}
private static void loadImage() throws IOException {
int newWidth = 80;
int newHeight = 40;
bi = ImageIO.read(RoundedButtonDemo1.class.getResource("/resources/login.png"));
bi = getScaledBufferedImage(bi, newWidth, newHeight);
}
public static BufferedImage getScaledBufferedImage(final Image img,
final int newWidth,
final int newHeight) {
final Dimension originalDim = new Dimension(img.getWidth(null), img.getHeight(null)),
containerDim = new Dimension(newWidth, newHeight),
resultDim = new Dimension();
collapseInside(resultDim, originalDim, containerDim);
final GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice gdev = genv.getDefaultScreenDevice();
final GraphicsConfiguration gcnf = gdev.getDefaultConfiguration();
final BufferedImage simg = gcnf.createCompatibleImage(resultDim.width, resultDim.height, Transparency.TRANSLUCENT);
//Painting input image to output image:
final Graphics2D g2d = simg.createGraphics();
g2d.drawImage(img, 0, 0, resultDim.width, resultDim.height, null); //@Docs "...is scaled if necessary.".
g2d.dispose();
return simg;
}
/**
* @param resultDim Output dimension (same aspect ratio as the original dimension, and inside containerDim).
* @param originalDim Original dimension.
* @param containerDim Dimension with the maximum width and maximum height.
*/
public static void collapseInside(final Dimension resultDim,
final Dimension originalDim,
final Dimension containerDim) {
resultDim.setSize(originalDim);
if (resultDim.width > containerDim.width) {
//Adjusting height for max width:
resultDim.height = (resultDim.height * containerDim.width)/resultDim.width;
resultDim.width = containerDim.width;
}
if (resultDim.height > containerDim.height) {
//Adjusting width for max height:
resultDim.width = (resultDim.width * containerDim.height)/resultDim.height;
resultDim.height = containerDim.height;
}
}
private static class CustomButton extends JPanel {
private Image img;
private String text;
public void setImage(final Image img) {
this.img = img;
final Dimension imgDim = new Dimension(img.getWidth(null), img.getHeight(null));
setMinimumSize(imgDim);
setPreferredSize(imgDim);
repaint();
}
public Image getImage() {
return img;
}
public void setText(final String text) {
this.text = text;
repaint();
}
public String getText() {
return text;
}
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
//Drawing the image:
g.drawImage(img, 0, 0, null);
//Drawing the text:
//For centering the text, I used code from:
//https://stackoverflow.com/questions/27706197/how-can-i-center-graphics-drawstring-in-java
final FontMetrics metrics = g.getFontMetrics(g.getFont());
final int x = (img.getWidth(null) - metrics.stringWidth(text))/2;
final int y = (img.getHeight(null) - metrics.getHeight())/2 + metrics.getAscent();
g.drawString(text, x, y);
}
}
private static void createAndShowGUI() {
final JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final CustomButton button = new CustomButton();
button.setSize(new Dimension(5, 5));
button.setImage(bi);
button.setText("Hello World");
//button.setHorizontalTextPosition(SwingConstants.CENTER);
//button.setOpaque(false);
//button.setBorder(BorderFactory.createLineBorder(Color.BLACK));
button.addMouseListener(new MouseListener() {
private int count = 0;
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == button) {
//Get the mouse click position (in pixels),
//relative to the top-left corner of label:
final Point relativeClickPoint = e.getPoint();
//Obtain alpha value from the TYPE_INT_ARGB pixel:
final int pixel = bi.getRGB(relativeClickPoint.x, relativeClickPoint.y);
final int alpha = bi.getColorModel().getAlpha(pixel);
if (alpha > 0) { //Check if the pixel is not transparent.
if (count % 2 == 0) {
button.setText("Bye");
} else {
button.setText("Hello World");
}
count++;
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
});
final JPanel singleCenteredComponentJPanel = new JPanel(new GridBagLayout());
singleCenteredComponentJPanel.add(button);
frame.add(singleCenteredComponentJPanel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Alternativ, wenn Sie normale Tasten wollen, istead von Etiketten, wie es scheint here Sie Tasten neu gestalten können auch!
Ansonsten habe ich auch folgendes versucht:
1) Unter Verwendung JLayeredPane
s. Es gibt eine tutorial, die sie erklärt, und ich vermute, dass sie wahrscheinlich eine Methode haben könnten, um die Reihenfolge des sichtbaren Bereichs für eine gegebene Point
oder etwas ähnliches zu erhalten, aber sie nicht.
2) Unter Verwendung von Container.getComponentAt(Point)
und Container.findComponentAt(Point)
in der MouseListener
, aber (wie ich nach dem Testen herausgefunden) diese Methoden nicht durchsichtig undurchsichtig (+ transparente) Pixel "durchschauen".
3) Suche nach Umformung oder Transluzenz in JPanel
s (inspiriert von How to Create Translucent and Shaped Windows), aber nichts gefunden.
4) How to Decorate Components with the JLayer Class mit erster Linie sagen:
... können Sie auf Komponenten und reagieren auf die Komponente Ereignisse ziehen, ohne direkt die zugrunde liegende Komponente zu modifizieren.
scheint vielversprechend, aber ich bin hier fertig.
Das ist es für mich für jetzt. Auf Wiedersehen.