可動コンポーネントを持つ JPanel があります。
私の問題は、パネルでアクションを使用すると、パネル全体のコンポーネントの位置が、位置を元に戻すのではなく、フレームの上部中央に変更されることです。私はそれをデバッグし、validate() から来ていることを知っています。validate() を手動で使用すると、アクションなしでも発生します。
パネルで使用されるコンポーネントのコードは次のとおりです。
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.designtime.DataSourcePlugin;
import com.inform_ac.utils.misc.gui.resizer.ComponentResizer;
/**
* AButton is a JAVA-Swing component with integrated functional buttons.
*/
public class AButton extends JPanel {
/**
* SerialVersionUID: 111111111L
*/
protected static final long serialVersionUID = 111111111L;
/**
* Standard font for displaying text.
*/
protected Font standardFont = new Font("Dialog", Font.PLAIN, 12);
/**
* Defining functional JButtons to delete and edit a AButton.
*/
protected ADeleteButton delBtn = new ADeleteButton(this);
protected JButton editBtn = new JButton();
protected String[] editOptionNames = { "Connect", "Deconnect", "Edit" };
protected JPopupMenu popupmenu = new JPopupMenu();
protected Dimension minDimension = new Dimension(120,120);
protected Point location = new Point();
protected DataFactory dataFactory;
protected DataSourcePlugin dataSourcePlugin;
/**
* Mode: 0 - moving
* 1 - connecting
*/
protected int mode = 0;
/**
* Defining the label for displaying OK or error images.
*/
protected JLabel lblIcon = new JLabel();
protected final JLabel lblInfo1 = new JLabel();
protected final JLabel lblInfo2 = new JLabel();
protected final JLabel lblInfo3 = new JLabel();
public final JButton connectBtn_right = new JButton();
public final JButton connectBtn_left = new JButton();
protected AButton parent;
protected ArrayList<AButton> children = new ArrayList<AButton>();
/**
* Identifier
*/
protected int id = 0;
/**
* Constructor with given start coordinates.
*
* @param X
* - coordinate
* @param Y
* - coordinate
*/
public AButton(int X, int Y, int index) {
this.id = index;
location = new Point(X,Y);
setBounds(location.x, location.y, minDimension.width, minDimension.height);
init();
}
/**
* Private method to initialize main components.
*/
private void init() {
initPnl();
initBtns();
setVisible(true);
setFocusable(true);
}
/**
* Private method to initialize the main panel.
*/
private void initPnl() {
setBackground(UIManager.getColor("InternalFrame.activeTitleBackground"));
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
setPreferredSize(minDimension);
setBorder(UIManager.getBorder("CheckBox.border"));
setFont(standardFont);
setLayout(null);
}
/**
* Private method to initialize functional {@linkplain JButton}.
*/
private void initBtns() {
initEditBtn();
initDelBtn();
initIconPnl();
initConnectorBtns();
}
/**
* Private method to initialize the delete button. Method have to refresh
* the size of this AButton to set the button on the top right corner of
* this AButton.
*/
private void initDelBtn() {
delBtn.setBounds(getWidth() - 18 - 2, 2, 18, 18);
delBtn.setFont(standardFont);
delBtn.setBackground(null);
delBtn.setBorderPainted(false);
delBtn.setBorder(null);
delBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
delBtn.setPreferredSize(new Dimension(16, 16));
delBtn.setMinimumSize(new Dimension(12, 12));
delBtn.setMaximumSize(new Dimension(20, 20));
delBtn.setIcon(new ImageIcon(AButton.class
.getResource("/javax/swing/plaf/metal/icons/ocean/close.gif")));
add(delBtn);
}
/**
* Private method to initialize the edit button.
*/
private void initEditBtn() {
initPopupmenu();
initMouseListener();
editBtn.setBounds(2,2,21,21);
editBtn.setFont(standardFont);
editBtn.setBorder(null);
editBtn.setBorderPainted(false);
editBtn.setBackground(UIManager
.getColor("InternalFrame.activeTitleGradient"));
editBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
editBtn.setAlignmentX(Component.CENTER_ALIGNMENT);
editBtn.setPreferredSize(new Dimension(21, 21));
editBtn.setMinimumSize(new Dimension(18, 18));
editBtn.setMaximumSize(new Dimension(25, 25));
editBtn.setIcon(new ImageIcon("C:\\Users\\akaradag\\Pictures\\JavaIcon\\icon_bearbeiten.gif"));
add(editBtn);
}
protected void initPopupmenu(){
for(int i = 0; i < editOptionNames.length; i++) {
popupmenu.add(new AbstractAction(editOptionNames[i]) {
private static final long serialVersionUID = 5550466652812249477L;
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Connect")) {
if (mode == 1) {
mode = 0;
showConnectors();
} else {
mode = 1;
showConnectors();
}
} else if (e.getActionCommand().equals("Deconnect")) {
resetConnections();
}
else if(e.getActionCommand().equals("Edit")) {
}
}
});
}
}
protected void initMouseListener()
{
editBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
popupmenu.show(e.getComponent(), e.getX(), e.getY());
}
});
}
/**
* Private method to display or not display the connector buttons
*/
public void showConnectors() {
boolean connect = false;
if (mode == 1) {
connect = true;
}
connectBtn_left.setVisible(connect);
connectBtn_right.setVisible(connect);
}
/**
* Private method to initialize the connector buttons
*/
private void initConnectorBtns() {
connectBtn_right.setCursor(Cursor
.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
connectBtn_right.setVisible(false);
connectBtn_right.setPreferredSize(new Dimension(15, 15));
connectBtn_right.setMinimumSize(new Dimension(12, 12));
connectBtn_right.setMaximumSize(new Dimension(15, 15));
connectBtn_right.setFont(new Font("Dialog", Font.PLAIN, 12));
connectBtn_right.setBorderPainted(false);
connectBtn_right.setBorder(null);
connectBtn_right.setBackground(SystemColor.activeCaption);
connectBtn_right
.setBounds(getWidth() - 16, getHeight() / 2 - 5, 15, 15);
add(connectBtn_right);
connectBtn_left.setCursor(Cursor
.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
connectBtn_left.setVisible(false);
connectBtn_left.setPreferredSize(new Dimension(25, 25));
connectBtn_left.setMinimumSize(new Dimension(12, 12));
connectBtn_left.setMaximumSize(new Dimension(15, 15));
connectBtn_left.setFont(new Font("Dialog", Font.PLAIN, 12));
connectBtn_left.setBorderPainted(false);
connectBtn_left.setBorder(null);
connectBtn_left.setBackground(SystemColor.activeCaption);
connectBtn_left.setBounds(2, getHeight() / 2 - 5, 15, 15);
add(connectBtn_left);
}
/**
* Private method to initialize the {@linkplain JLabel} for displaying
* informations.
*/
private void initIconPnl() {
lblIcon.setHorizontalTextPosition(SwingConstants.CENTER);
lblIcon.setHorizontalAlignment(SwingConstants.CENTER);
lblIcon.setAlignmentX(Component.CENTER_ALIGNMENT);
lblIcon.setIcon(new ImageIcon(AButton.class
.getResource("/javax/swing/plaf/metal/icons/ocean/error.png")));
lblIcon.setBorder(null);
lblIcon.setFont(new Font("Dialog", Font.PLAIN, 12));
lblIcon.setBounds(getWidth() / 4, 3, getWidth() / 2,
getHeight() / 4 + 2);
lblIcon.setLayout(null);
add(lblIcon);
lblInfo1.setFont(new Font("Tahoma", Font.BOLD, getHeight() / 10));
lblInfo1.setForeground(SystemColor.desktop);
lblInfo1.setBounds(22, getHeight() / 2 - 5, getWidth() - 42,
getHeight() / 8);
add(lblInfo1);
lblInfo2.setFont(new Font("Tahoma", Font.BOLD, getHeight() / 10));
lblInfo2.setForeground(Color.BLACK);
lblInfo2.setBounds(10, getHeight() / 2 - 5 + getHeight() / 8 + 5,
getWidth() - 20, getHeight() / 8);
add(lblInfo2);
lblInfo3.setFont(new Font("Tahoma", Font.BOLD, getHeight() / 10));
lblInfo3.setForeground(Color.BLACK);
lblInfo3.setBounds(10, getHeight() / 2 - 5 + 2 * (getHeight() / 8 + 5),
getWidth() - 20, getHeight() / 8);
add(lblInfo3);
}
public String getLblInfo(int index) {
if (index == 1) {
return lblInfo1.getText();
} else if (index == 2) {
return lblInfo2.getText();
} else {
return lblInfo3.getText();
}
}
public void setLblInfo(String text, int index) {
if (index == 1) {
lblInfo1.setText(text);
} else if (index == 2) {
lblInfo2.setText(text);
} else {
lblInfo3.setText(text);
}
}
public Point getLocation() {
return new Point(getX(), getY());
}
public Point getInputLocation() {
return connectBtn_left.getLocation();
}
/**
* Methode um die Location des Objektes zu ändern und dies auch zu repainten.
* Dient dazu damit der Fehler das wenn ein Objekt gelöscht wird die restlichen in die Mitte
* wandern.
*/
public void setLocation(Point p){
location = p;
}
public Point getOutputLocation() {
return connectBtn_right.getLocation();
}
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
showConnectors();
}
public JButton getDelBtn() {
return delBtn;
}
public int getIndex() {
return id;
}
public void setIndex(int index) {
this.id = index;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setLocation(location.x, location.y);
if (lblInfo1.getText().equals("Join")) {
if (children.size() == 2) {
lblIcon.setIcon(new ImageIcon(
"C:\\Users\\akaradag\\Pictures\\JavaIcon\\ok-icon.png"));
} else if (children.size() > 2) {
lblIcon.setIcon(new ImageIcon(
AButton.class
.getResource("/javax/swing/plaf/metal/icons/ocean/warning.png")));
} else {
lblIcon.setIcon(new ImageIcon(
AButton.class
.getResource("/javax/swing/plaf/metal/icons/ocean/error.png")));
}
} else if (lblInfo1.getText().equals("JDBC")
|| lblInfo1.getText().equals("File")) {
if (parent != null) {
lblIcon.setIcon(new ImageIcon(
"C:\\Users\\akaradag\\Pictures\\JavaIcon\\ok-icon.png"));
} else {
lblIcon.setIcon(new ImageIcon(
AButton.class
.getResource("/javax/swing/plaf/metal/icons/ocean/error.png")));
}
}
}
public void setOutput(AButton out) {
parent = out;
}
public AButton getOutput() {
return parent;
}
public void addInput(AButton input) {
if (!contains(input)) {
this.children.add(input);
}
}
private boolean contains(AButton in) {
for (int i = 0; i < this.children.size(); i++) {
if (this.children.get(i).getIndex() == in.getIndex()) {
return true;
}
}
return false;
}
public ArrayList<AButton> getInput() {
return this.children;
}
public void removeFromInput(AButton remove) {
for (int i = 0; i < this.children.size(); i++) {
if (this.children.get(i) != null) {
if (this.children.get(i).getIndex() == remove.getIndex()) {
this.children.remove(i);
}
}
}
}
public void resetConnections() {
if (parent != null) {
ArrayList<AButton> in = parent.getInput();
for (int i = 0; i < in.size(); i++) {
if (in.get(i).getIndex() == id) {
in.remove(i);
}
}
parent = null;
}
for (int i = 0; i < this.children.size(); i++) {
this.children.get(i).setOutput(null);
this.children.get(i).repaint();
}
this.children = new ArrayList<AButton>();
// if(connectionsDeletedNotify != null)
// connectionsDeletedNotify.actionPerformed(new ActionEvent(this, 0, "Deconnect"));
}
/**
* Setter for the DataFactory
* @param df
*/
public void setDataFactory(DataFactory df)
{
this.dataFactory = df;
}
/**
* Getter for the DataFactory
* @return
*/
public DataFactory getDataFactory()
{
return this.dataFactory;
}
public DataSourcePlugin getDataSourcePlugin() {
return dataSourcePlugin;
}
public void setDataSourcePlugin(DataSourcePlugin dataSourcePlugin) {
this.dataSourcePlugin = dataSourcePlugin;
}
}
これがメインパネルのコードです
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import org.pentaho.reporting.designer.core.settings.WorkspaceSettings;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.designtime.DataSourcePlugin;
import org.pentaho.reporting.engine.classic.core.designtime.DefaultDataFactoryChangeRecorder;
import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.inform_ac.reporting.datasource.dataintegrator.frontend.DataintegratorDesignTimeContext;
import com.inform_ac.reporting.datasource.dataintegrator.frontend.component.AButton;
import com.inform_ac.reporting.datasource.dataintegrator.frontend.component.AConfirmDialog;
import com.inform_ac.reporting.datasource.dataintegrator.frontend.component.ADeleteButton;
public class DataintegratorMainPanel extends JPanel {
DataintegratorDesignTimeContext context;
JPopupMenu popmen = new JPopupMenu();
JMenuItem menu1 = new JMenuItem("Add new Datasource:");
JMenuItem menu2 = new JMenuItem("Join");
Dimension dim = new Dimension();
Point holdingPoint , point1, point2;;
/**
* ArrayList für die visuellen Datasources
*/
ArrayList<AButton> abuttonList = new ArrayList<AButton>();
/**
* Nummerierungen der abuttons
*/
int index = 0;
/**
* The <code>Logger</code> of this instance
*/
protected final static Logger LOGGER = LoggerFactory.getLogger(DataintegratorQueryPanel.class);
private static final long serialVersionUID = 4705352682546516889L;
public DataintegratorMainPanel() {
initPopupMenu();
initMouseListener();
}
protected void initMouseListener()
{
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3){
popmen.show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
/**
* Überschrift bei Rechtsklick
* @param header
* @return JComponent
*/
protected JComponent createHeader(String header) {
JLabel label = new JLabel(header);
label.setFont(label.getFont().deriveFont(Font.BOLD,14));
label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
return label;
}
protected void giveMouseListenerTo(AButton button) {
button.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
AButton tmp = (AButton) me.getSource();
//Mode Moving
if(tmp.getMode()==0){
Point point = getMousePosition();
//Über den Rand raus
if(point != null) {
point.x = point.x - holdingPoint.x;
point.y = point.y - holdingPoint.y;
if(point.x >= 0 && point.y >= 0) {
tmp.setLocation(point);
}
//LOGGER.info(""+point);
}
}
else if (tmp.getMode()==1) {
point2 = getMousePosition();
}
repaint();
}
});
button.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
AButton tmp = (AButton) me.getSource();
if (tmp.getMode() == 0) {
holdingPoint = tmp.getMousePosition();
}
else if (tmp.getMode() == 1) {
Point tmp_point = tmp.getLocation();
point1 = new Point(tmp.connectBtn_right.getLocation().x+tmp_point.x,tmp.connectBtn_right.getLocation().y+tmp_point.y);
LOGGER.info("point1: "+point1);
}
}
@Override
public void mouseReleased(MouseEvent me) {
super.mouseReleased(me);
try {
AButton destination = (AButton) getComponentAt(getMousePosition());
AButton source = (AButton) me.getSource();
if (destination != null && source.getMode() == 1) {
// Hier muss der Baum verkettet werden
if (destination != source) {
destination.addInput(source);
if (source.getOutput() == null) {
source.setOutput(destination);
} else {
AButton tmp = source.getOutput();
tmp.removeFromInput(source);
source.setOutput(destination);
}
source.setMode(0);
destination.setMode(0);
}
}
} catch (ClassCastException e) {
point2 = null;
}
point1 = null;
point2 = null;
repaint();
}
});
repaint();
}
protected void initPopupMenu() {
popmen.add(createHeader("Neue Datasource"));
popmen.addSeparator();
context = new DataintegratorDesignTimeContext(new MasterReport());
final DataFactoryMetaData[] datas = DataFactoryRegistry.getInstance()
.getAll();
for (final DataFactoryMetaData data : datas) {
// Some of the DataFactories are not needed
if (data.isHidden()) {
continue;
} else if (!WorkspaceSettings.getInstance().isShowExpertItems()
&& data.isExpert()) {
continue;
} else if (!WorkspaceSettings.getInstance().isShowDeprecatedItems()
&& data.isDeprecated()) {
continue;
} else if (!WorkspaceSettings.getInstance()
.isExperimentalFeaturesVisible() && data.isExperimental()) {
continue;
} else if (!data.isEditorAvailable()) {
continue;
}
if (data.getDisplayName(getLocale()).equals("Dataintegrator")) {
continue;
}
JMenuItem item = new JMenuItem(new AbstractAction(
data.getDisplayName(getLocale())) {
private static final long serialVersionUID = 7700562297221703939L;
@Override
public void actionPerformed(ActionEvent arg0) {
Point mousePos = getMousePosition();
final AButton tmp = new AButton(mousePos.x,mousePos.y,index++);
// Action listener hier und nicht in die for schleife
tmp.getDelBtn().addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
ADeleteButton tmp_1 = (ADeleteButton) arg0
.getSource();
AButton source = tmp_1.getAbutton();
AConfirmDialog dialog = new AConfirmDialog();
int opt = dialog.getState();
if (opt == 1) {
for (int i = 0; i < abuttonList.size(); i++) {
if (source.getIndex() != abuttonList.get(i)
.getIndex()) {
if (abuttonList.get(i).getOutput() != null
&& abuttonList.get(i).getOutput()
.getIndex() == source
.getIndex()) {
abuttonList.get(i).setOutput(null);
}
abuttonList.get(i).removeFromInput(source);
}
}
// seperat erst die referenzen löschen dann das
// objekt aus der liste
for (int i = 0; i < abuttonList.size(); i++) {
if (source.getIndex() == abuttonList.get(i)
.getIndex()) {
abuttonList.remove(i);
source.setVisible(false);
source.setEnabled(false);
}
}
}
}
});
LOGGER.info("--> data: " + data);
final DataSourcePlugin editor = data.createEditor();
LOGGER.info("--> editor: " + editor);
final DefaultDataFactoryChangeRecorder recorder = new DefaultDataFactoryChangeRecorder();
final DataFactory dataFactory = editor.performEdit(context,
null, null, recorder);
LOGGER.info("--> datafactory: " + dataFactory);
// Falls die Datafactory initialisiert werden konnte
if (dataFactory != null) {
tmp.setDataSourcePlugin(editor);
tmp.setDataFactory(dataFactory);
add(tmp);
//LOGGER.info("New datafact"+mousePos);
abuttonList.add(tmp);
//Moving listener
giveMouseListenerTo(tmp);
validate();
}
}
});
popmen.add(item);
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(1.5f));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Line2D tmp_line;
for (int i = 0; i < abuttonList.size(); i++) {
if (abuttonList.get(i).getOutput() != null) {
g2d.setStroke(new BasicStroke(1.5f));
int x1 = abuttonList.get(i).getLocation().x
+ abuttonList.get(i).connectBtn_right.getLocation().x;
int y1 = abuttonList.get(i).getLocation().y
+ abuttonList.get(i).connectBtn_right.getLocation().y;
int x2 = abuttonList.get(i).getOutput().getLocation().x
+ abuttonList.get(i).getOutput().connectBtn_left
.getLocation().x - 4;
int y2 = abuttonList.get(i).getOutput().getLocation().y
+ abuttonList.get(i).getOutput().connectBtn_left
.getLocation().y;
tmp_line = new Line2D.Double(x1, y1, x2, y2);
double m = (y2 - y1) / (double) (x2 - x1);
//logger.info("m: "+m);
int vz = x2-x1;
//LOGGER.info("vz: "+vz);
if(vz<0)
{
vz = 20;
}
else if (vz>0){
vz = -20;
}
if(m<4 && m>-4) {
Point p = new Point(x2 -20, (int) (y1 + m * (x2 - x1 - 20)));
//logger.info(p.toString());
Line2D tmp2_line = new Line2D.Double(x2, y2, x2 + vz,
p.y + 3);
//logger.info("x2: "+x2+", y2: "+y2+", p.y:"+p.y);
Line2D tmp3_line = new Line2D.Double(x2, y2, x2 + vz,
p.y - 3);
//logger.info("x2: "+x2+", y2: "+y2+", p.y:"+p.y);
g2d.setPaint(Color.BLACK);
g2d.draw(tmp2_line);
g2d.draw(tmp3_line);
}
g2d.draw(tmp_line);
}
}
if (point1 != null && point2 != null) {
Line2D line2d = new Line2D.Double(point1, point2);
g2d.setPaint(Color.RED);
g2d.setStroke(new BasicStroke(1.5f));// set stroke size
g2d.draw(line2d);
}
}
}
そのため、editBtn をクリックして、たとえば Connect をクリックすると、エラーが発生します。パネル全体を再描画し、パネル内のボタンがパネルの中央上部に垂直に配置され、オブジェクト自体に保存されている場所に戻ります。
また、validate() を使用してエラーを再現できます。
ここで何が問題なのかわかりません。検証後にメイン パネルのコンポーネントの場所を変更するのはなぜですか?
コードが SSCCE でない場合は申し訳ありませんが、pentaho ライブラリがないと動作しませんでした...