[英]how position a JDialog relative to a JPanel within a JFrame
下面是一些代碼,顯示了我的問題的本質。 我展示了一個包含黃色和綠色JPanel
的JFrame
。 這是擴展JPanel
並實現Mouselistener
的同一 class 的兩個對象。
我想要的是,如果用戶在任一面板上單擊鼠標右鍵,則會在鼠標位置彈出一個JDialog
。 唉,它沒有,我根本不知道如何獲得正確的行為(在嘗試了很多事情之后)。 你能幫助我嗎?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DialogPositioning extends JFrame {
public DialogPositioning() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add two silly panels, then show this JFrame object
add(new NonsensePanel(Color.YELLOW), BorderLayout.NORTH);
add(new NonsensePanel(Color.GREEN), BorderLayout.CENTER);
pack();
setVisible(true);
}
private class NonsensePanel extends JPanel implements MouseListener {
NonsensePanel(Color bgColor) {
setPreferredSize(new Dimension(200,200));
setBackground(bgColor);
addMouseListener(this);
}
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
new NonsenseDialog(this, e.getX(), e.getY()); //popup a home-made JDialog at mouse position
}
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
}
private class NonsenseDialog extends JDialog {
NonsenseDialog(Component c, int x, int y) {
//Add a simple, emmpty panel to this JDialog so that there is something to see, then show this JDialog at the x,y position relative to Component c
JPanel pnl = new JPanel();
pnl.setPreferredSize(new Dimension(100, 100));
add(pnl);
pack();
setModal(true);
setLocationRelativeTo(c); //Should ensure the dialog pops up at posn x,y relative to the top/left corner of ...
setLocation(x, y); //... Component c (in our case the yellow or green NonsensePanel objects). DOES NOT WORK???
setVisible(true);
}
}
public static void main(String[] args) {
new DialogPositioning();
}
}
MouseEvent
的getPoint()
方法將返回相對於面板的點。
setLocation(...)
方法設置JDialog
相對於屏幕。
所以你需要將鼠標點轉換為屏幕位置。
我會更改您的 NonsenseDialog 以接收鼠標點作為參數(而不是單獨的 x/y 值)。
因此,您將使用MouseEvent
的getPoint()
方法傳遞給您的 class。
然后在您的 class 的構造函數中,您可以使用:
Point location = SwingUtilities.convertPointToScreen(...);
setLocation( location );
編輯:您應該使用 camickr 的答案,因為它是更好的解決方案。
您在這里遇到的問題是, e.getX()
和e.getY()
返回的坐標是相對於您單擊的相應JPanel
的。 但是當您將這些坐標傳遞到您的JDialog
並將它們與setLocation(x, y)
一起使用時,這些坐標將相對於您的屏幕。
您缺少原始坐標和目標坐標之間的映射。
如果您想保留自定義對話框而不使用例如JPopupMenu
(免費提供此功能),您可以復制JPopupMenu#show()
處理此問題的方式。 (見這里)
對於您的示例,使用上面鏈接中的代碼,對NonsenseDialog
的更改應如下所示:
private class NonsenseDialog extends JDialog {
NonsenseDialog(Component c, int x, int y) {
// code taken from jpopupmenu#show
Point invokerOrigin;
if (c != null) {
invokerOrigin = c.getLocationOnScreen();
// To avoid integer overflow
long lx, ly;
lx = ((long) invokerOrigin.x) + ((long) x);
ly = ((long) invokerOrigin.y) + ((long) y);
if (lx > Integer.MAX_VALUE)
lx = Integer.MAX_VALUE;
if (lx < Integer.MIN_VALUE)
lx = Integer.MIN_VALUE;
if (ly > Integer.MAX_VALUE)
ly = Integer.MAX_VALUE;
if (ly < Integer.MIN_VALUE)
ly = Integer.MIN_VALUE;
setLocation((int) lx, (int) ly);
} else {
setLocation(x, y);
}
// your code here
setVisible(true);
}
}
它的作用是,它從您單擊的組件(您的JPanel
)中獲取坐標,並將您傳遞給對話框的坐標(相對於面板的坐標)添加,然后使用生成的坐標來設置對話框的位置。 使用這種方法,您的對話框應該會在右鍵單擊的原點彈出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.