伙計們,我想知道是否有辦法使其arrow僅使用 X 軸即可拖動。我在null layout這里使用了一個,這arrow是一個jlabel已添加到jframe. 這是更多資訊的影像。先感謝您。
(我已經編輯它來顯示我的一些代碼解決了這個問題之前,已經顯示出這里的代碼是差不多的ImageIcon,JLabel和的某些部分JFrame)
public class Level03 extends JFrame implements ActionListener, MouseListener, WindowListener {
// These are the Global Variables of the Level03 Class
ImageIcon slide = new ImageIcon("slide to unlock.png");
ImageIcon slideButton = new ImageIcon("arrow icon.png");
JLabel slideLabel = new JLabel(slide);
JLabel slideArrow = new JLabel(slideButton);
Level03 (){ // This is the constructor
// This is just setting the bounds of the arrow on the JFrame
slideLabel.setBounds(100,350, 400,50);
slideArrow.setBounds(117,350,50,50); // slideArrow is the JLabel with the ImageIcon that looks like an arrow.
slideArrow.addMouseListener(this);
mainFrame.add(slideArrow);
mainFrame.add(slideLabel);
}
筆記!!!我在下面也有這些覆寫implements ActionListener, MouseListener, WindowListener
@Override
public void actionPerformed(ActionEvent e){}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}

uj5u.com熱心網友回復:
用 a 做這種事情JLabel并非不可能,只是,復雜。
就個人而言,我很想只使用自定義繪制的路線,因為它為您提供了所有控制權。
例如...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws IOException {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new SlideToUnlock());
}
}
public class SlideToUnlock extends JPanel {
private String text;
private Image indicatorImage;
private Rectangle indicatorBounds;
private Integer clickXOffset; // I can make it null and then ignore it
private Integer dragX; // The x position of the drag
public SlideToUnlock() throws IOException {
indicatorImage = ImageIO.read(getClass().getResource("/images/ArrowRight.png"));
setText("Slide to unlock");
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
resetTimer();
Rectangle bounds = getIndiciatorImageBounds();
if (bounds.contains(e.getPoint())) {
clickXOffset = e.getPoint().x - bounds.x;
} else {
clickXOffset = null;
}
dragX = null;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
invalidate();
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
dragX = e.getPoint().x;
if (didReachTheOtherSide()) {
// Notifiy some kind of observer
}
repaint();
}
};
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
@Override
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(getFont());
Image indicatorImage = getIndicatorImage();
Insets insets = getInsets();
int imageWidth = 0;
int imageHeight = 0;
if (indicatorImage != null) {
imageWidth = indicatorImage.getWidth(this);
imageHeight = indicatorImage.getHeight(this);
}
int height = Math.max(fm.getHeight(), imageHeight)
1 // Border
8; // Inner track
int width = 1 8 fm.stringWidth(getText()) imageWidth;
width = insets.left insets.right;
height = insets.top insets.top;
return new Dimension(width, height);
}
@Override
public void invalidate() {
super.invalidate();
indicatorBounds = null;
clickXOffset = null;
dragX = null;
}
@Override
public void revalidate() {
super.revalidate();
indicatorBounds = null;
clickXOffset = null;
dragX = null;
}
protected boolean didReachTheOtherSide() {
Rectangle bounds = getIndiciatorImageBounds();
return bounds.x bounds.width >= getWidth() - 1;
}
protected Rectangle getIndiciatorImageBounds() {
if (getParent() == null) {
return null;
}
if (dragX == null && indicatorBounds != null) {
return indicatorBounds;
}
Image indicatorImage = getIndicatorImage();
int indicatorX = 1;
int indicatorY = (getHeight() - indicatorImage.getHeight(this)) / 2;
indicatorBounds = new Rectangle(indicatorX, indicatorY, indicatorImage.getWidth(this), indicatorImage.getHeight(this));
if (dragX != null) {
indicatorBounds.x = (indicatorBounds.x - clickXOffset) dragX;
if (indicatorBounds.x indicatorBounds.width > (getWidth() - 1)) {
indicatorBounds.x = getWidth() - indicatorBounds.width - 1;
} else if (indicatorBounds.x < 1) {
indicatorBounds.x = 1;
}
}
return indicatorBounds;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Image getIndicatorImage() {
return indicatorImage;
}
public void setIndicatorImage(Image indicatorImage) {
this.indicatorImage = indicatorImage;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int cornerRadius = 16;
paintText(g2d);
paintOverlay(g2d);
paintIndicator(g2d);
g2d.setColor(getForeground());
g2d.draw(new RoundRectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1, cornerRadius, cornerRadius));
g2d.dispose();
}
protected void paintOverlay(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
Rectangle bounds = getIndiciatorImageBounds();
g2d.fillRect(1, 1, bounds.x bounds.width, getHeight() - 2);
g2d.dispose();
}
protected void paintText(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getForeground());
FontMetrics fm = g2d.getFontMetrics();
String text = getText();
int xPos = getWidth() - 1 - 4 - fm.stringWidth(text);
int yPos = ((getHeight() - fm.getHeight()) / 2) fm.getAscent();
g2d.drawString(text, xPos, yPos);
g2d.dispose();
}
protected void paintIndicator(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = getIndiciatorImageBounds();
g2d.translate(bounds.x, bounds.y);
Image indicatorImage = getIndicatorImage();
g2d.drawImage(indicatorImage, 0, 0, this);
g2d.dispose();
}
}
}
好的,所以,這“有效”,它完成了作業,但它缺少一些東西??......反彈!當用戶松開滑動控制元件時,它應該為反彈影片!
(我打賭你很抱歉你現在問了)

啊,那更好,是小細節造就了它??
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws IOException {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new SlideToUnlock());
}
}
public class SlideToUnlock extends JPanel {
private String text;
private Image indicatorImage;
private Rectangle indicatorBounds;
private Integer clickXOffset; // I can make it null and then ignore it
private Integer dragX; // The x position of the drag
private Timer reboundTimer;
public SlideToUnlock() throws IOException {
indicatorImage = ImageIO.read(getClass().getResource("/images/ArrowRight.png"));
setText("Slide to unlock");
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
resetReboundTimer();
Rectangle bounds = getIndiciatorImageBounds();
if (bounds.contains(e.getPoint())) {
clickXOffset = e.getPoint().x - bounds.x;
} else {
clickXOffset = null;
}
dragX = null;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
startReboundTimer();
}
@Override
public void mouseDragged(MouseEvent e) {
dragX = e.getPoint().x;
if (didReachTheOtherSide()) {
// Notifiy some kind of observer
}
repaint();
}
};
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
protected void resetReboundTimer() {
if (reboundTimer == null) {
return;
}
reboundTimer.stop();
reboundTimer = null;
}
protected void startReboundTimer() {
resetReboundTimer();
Rectangle bounds = getIndiciatorImageBounds();
clickXOffset = 0;
dragX = bounds.x (bounds.width / 2);
int lowerRange = 1 (bounds.width / 2);
int upperRange = getWidth() - 1 - (bounds.width / 2);
int fullRange = upperRange - lowerRange;
int currentRange = (bounds.x (bounds.width / 2)) - lowerRange;
double progressRange = currentRange / (double) fullRange;
Duration fullDuration = Duration.ofMillis(250);
Duration desiredDuration = Duration.ofMillis((long) (fullDuration.toMillis() * progressRange));
int remainingRange = (int) (fullRange * progressRange);
reboundTimer = new Timer(5, new ActionListener() {
private Instant startTime = null;
@Override
public void actionPerformed(ActionEvent e) {
if (startTime == null) {
startTime = Instant.now();
}
Duration runTime = Duration.between(startTime, Instant.now());
double runTimeProgress = runTime.toMillis() / (double) desiredDuration.toMillis();
if (runTimeProgress >= 1.0) {
resetReboundTimer();
invalidate();
} else {
dragX = (int) (remainingRange * (1.0 - runTimeProgress));
}
repaint();
}
});
reboundTimer.setInitialDelay(0);
reboundTimer.start();
}
@Override
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(getFont());
Image indicatorImage = getIndicatorImage();
Insets insets = getInsets();
int imageWidth = 0;
int imageHeight = 0;
if (indicatorImage != null) {
imageWidth = indicatorImage.getWidth(this);
imageHeight = indicatorImage.getHeight(this);
}
int height = Math.max(fm.getHeight(), imageHeight)
1 // Border
8; // Inner track
int width = 1 8 fm.stringWidth(getText()) imageWidth;
width = insets.left insets.right;
height = insets.top insets.top;
return new Dimension(width, height);
}
@Override
public void invalidate() {
super.invalidate();
indicatorBounds = null;
clickXOffset = null;
dragX = null;
}
@Override
public void revalidate() {
super.revalidate();
indicatorBounds = null;
clickXOffset = null;
dragX = null;
}
protected boolean didReachTheOtherSide() {
Rectangle bounds = getIndiciatorImageBounds();
return bounds.x bounds.width >= getWidth() - 1;
}
protected Rectangle getIndiciatorImageBounds() {
if (getParent() == null) {
return null;
}
if (dragX == null && indicatorBounds != null) {
return indicatorBounds;
}
Image indicatorImage = getIndicatorImage();
int indicatorX = 1;
int indicatorY = (getHeight() - indicatorImage.getHeight(this)) / 2;
indicatorBounds = new Rectangle(indicatorX, indicatorY, indicatorImage.getWidth(this), indicatorImage.getHeight(this));
if (dragX != null) {
indicatorBounds.x = (indicatorBounds.x - clickXOffset) dragX;
if (indicatorBounds.x indicatorBounds.width > (getWidth() - 1)) {
indicatorBounds.x = getWidth() - indicatorBounds.width - 1;
} else if (indicatorBounds.x < 1) {
indicatorBounds.x = 1;
}
}
return indicatorBounds;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Image getIndicatorImage() {
return indicatorImage;
}
public void setIndicatorImage(Image indicatorImage) {
this.indicatorImage = indicatorImage;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int cornerRadius = 16;
paintText(g2d);
paintOverlay(g2d);
paintIndicator(g2d);
g2d.setColor(getForeground());
g2d.draw(new RoundRectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1, cornerRadius, cornerRadius));
g2d.dispose();
}
protected void paintOverlay(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
Rectangle bounds = getIndiciatorImageBounds();
g2d.fillRect(1, 1, bounds.x bounds.width, getHeight() - 2);
g2d.dispose();
}
protected void paintText(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getForeground());
FontMetrics fm = g2d.getFontMetrics();
String text = getText();
int xPos = getWidth() - 1 - 4 - fm.stringWidth(text);
int yPos = ((getHeight() - fm.getHeight()) / 2) fm.getAscent();
g2d.drawString(text, xPos, yPos);
g2d.dispose();
}
protected void paintIndicator(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = getIndiciatorImageBounds();
g2d.translate(bounds.x, bounds.y);
Image indicatorImage = getIndicatorImage();
g2d.drawImage(indicatorImage, 0, 0, this);
g2d.dispose();
}
}
}
現在,使用標簽執行此操作將遵循非常相似的程序,唯一的補充是,您必須自己管理標簽大小和位置(因為大多數布局管理器不允許您這樣做)
以下是一些通過標簽拖動標簽的示例 MouseMotionListener
- JLabel 無法使用滑鼠運動偵聽器正確移動,為什么?
- 如何防止 JLabel 位置重置?
- JLabels, that store ImageIcons, are returned back to original location when the mouse is clicked in the panel
- How to make draggable components with ImageIcon
Now, in your case, you don't really care about the y position, so that can remain centred relative to the container (or the track) and you'd just need to update the x position based on the click offset and the current drag position. Complications arise in the fact that you'd need to be monitoring the label for drags, but converting the position of the movement to the parent container. Doable, but it's an additional complication
With a JLabel
The basic workflow is the same, except now you need to manage the component state of the label (in fact labels, because I assume you'll also want to have some text).
這是一個允許您拖動標簽的基本示例,它的核心作業流程與前面的示例基本相同,但它增加了需要管理組件大小和位置的開銷
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws IOException {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new SlideToUnlock());
}
}
public class SlideToUnlock extends JPanel {
private JLabel indicatorLabel;
private JPanel overLayPane;
private JLabel textLabel;
private Integer clickXOffset;
private Integer dragX;
public SlideToUnlock() throws IOException {
setLayout(null);
setBorder(new LineBorder(getForeground(), 1, true));
indicatorLabel = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/images/ArrowRight.png"))));
indicatorLabel.setBounds(1, 1, indicatorLabel.getPreferredSize().width, indicatorLabel.getPreferredSize().height);
add(indicatorLabel);
overLayPane = new JPanel();
add(overLayPane);
textLabel = new JLabel("Slide to unlock");
textLabel.setBounds(1, 1, textLabel.getPreferredSize().width, textLabel.getPreferredSize().height);
add(textLabel);
MouseAdapter mouseAdapter = new MouseAdapter() {
protected void resetDrag() {
clickXOffset = null;
dragX = null;
}
@Override
public void mousePressed(MouseEvent e) {
Point point = e.getPoint();
Point localPoint = SwingUtilities.convertPoint(SlideToUnlock.this, point, indicatorLabel);
if (indicatorLabel.getBounds().contains(localPoint)) {
clickXOffset = point.x - indicatorLabel.getBounds().x;
} else {
resetDrag();
}
}
@Override
public void mouseReleased(MouseEvent e) {
resetDrag();
doLayout();
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
dragX = e.getPoint().x;
doLayout();
repaint();
}
};
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
@Override
public void doLayout() {
Dimension preferredSize = indicatorLabel.getPreferredSize();
int xPos = 1;
if (dragX != null) {
xPos = (1 - clickXOffset) dragX;
if (xPos preferredSize.width > (getWidth() - 1)) {
xPos = getWidth() - preferredSize.width - 1;
} else if (xPos < 1) {
xPos = 1;
}
}
indicatorLabel.setBounds(xPos, 1, indicatorLabel.getPreferredSize().width, getHeight() - 2);
overLayPane.setBounds(1, 1, indicatorLabel.getX() indicatorLabel.getWidth() - 1, getHeight() - 2);
textLabel.setBounds(getWidth() - textLabel.getPreferredSize().width - 4, 1, textLabel.getPreferredSize().width, getHeight() - 2);
}
@Override
public Dimension getPreferredSize() {
Dimension preferredSize = indicatorLabel.getPreferredSize();
preferredSize.width = preferredSize.width * 4;
int height = Math.max(indicatorLabel.getPreferredSize().height, textLabel.getPreferredSize().height);
int width = indicatorLabel.getPreferredSize().width 4 textLabel.getPreferredSize().width 4 1;
Insets insets = getInsets();
width = insets.left insets.right;
height = insets.top insets.bottom;
return new Dimension(width, height);
}
}
}
這是一個快速的“黑客”。您需要提供附加功能來更改文本,支持更改背景顏色并在更改時更新狀態
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/386979.html
