31. august 2010 - 15:22Der er
10 kommentarer og 1 løsning
Applikation i Netbeans Platform
Jeg forsøger at konstruere en applikation i Netbeans Platform, hvilket også går fint nok som udgangspunkt. I denne applikation vil jeg gerne have et billede, som brugeren kan trække over i et jPanel via musen. Dette virker fint nok i en almindelig java-applikation. Her er koden:
public static void main(String[] args) { JFrame f = new JFrame("Selectable Icon"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setContentPane(new SelectablePanel()); f.setSize(590, 400); f.setLocation(200, 200); f.setVisible(true); } }
/** * Mouse code to enable image dragging from * ImageSelectionPanel to MainDisplayPanel * both located in SelectablePanel. */ class SelectableAction extends MouseInputAdapter {
/** * Contains both ImageSelectionPanel (on top) and MainDisplayPanel, * and uses SelectableAction mouse event code to facilitate * the dragging of images from the top to the bottom panel. */ class SelectablePanel extends JPanel {
ImageSelectionPanel selectionPanel; MainDisplayPanel mainPanel; SelectableAction action; Image image; Point p;
public SelectablePanel() { selectionPanel = new ImageSelectionPanel(); mainPanel = new MainDisplayPanel(); p = new Point(); setOpaque(true); // for content pane just in case setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = gbc.REMAINDER; gbc.weightx = 1.0; gbc.fill = gbc.HORIZONTAL; add(selectionPanel, gbc); gbc.weighty = 1.0; gbc.fill = gbc.BOTH; add(mainPanel, gbc); action = new SelectableAction(this, selectionPanel, mainPanel); addMouseListener(action); addMouseMotionListener(action); }
/** * Paints the image of the JLabel selected in ImageSelectionPanel * over selectionPanel, imagePanel and all components of each as * long as dragging == true in SelectableAction. */ @Override public void paint(Graphics g) { super.paint(g); if (action.dragging) { g.drawImage(image, p.x, p.y, this); } }
/** * Upper panel with purple background in SelectablePanel. * Icons can be selected and their images dragged down into * MainPanel where they are set as JLabels(icon). */ class ImageSelectionPanel extends JPanel {
JLabel[] labels;
public ImageSelectionPanel() { Image[] images = loadImages(); createLabels(images); addComponents(); setBorder(BorderFactory.createTitledBorder("click and drag to main panel")); setBackground(new Color(240, 200, 240)); }
private void createLabels(Image[] images) { labels = new JLabel[images.length]; for (int i = 0; i < images.length; i++) { labels[i] = new JLabel(new ImageIcon(images[i])); labels[i].setBorder(BorderFactory.createEtchedBorder()); } }
private void addComponents() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(2, 5, 2, 5); gbc.weightx = 1.0; for (int i = 0; i < labels.length; i++) { add(labels[i], gbc); } }
Når jeg så forsøger, at bruge denne kode i føromtalte Netbeans Platform, så giver det exceptions. Jeg går ud fra, at årsagen er, at filen ikke kan findes af applikationen.
Jeg har lavet et modul, hvor jeg også har lagt billed-filen. Dette modul bruger jeg så i et moduleSuite. Kode-stumpen derfra, hvori jeg forsøger at gøre det, ser således ud:
class ImageSelectionPanel extends JPanel {
JLabel[] labels; //protected String[] fileNames;//WORKING public String[] fileNames={"GreyU", "GreenB"};
public ImageSelectionPanel() { Image[] images = loadImages(); createLabels(images); addComponents(); setBorder(BorderFactory.createTitledBorder("click and drag to main panel")); setBackground(new Color(240, 200, 240)); }
private void createLabels(Image[] images) { labels = new JLabel[images.length]; for (int i = 0; i < images.length; i++) { labels[i] = new JLabel(new ImageIcon(images[i])); labels[i].setBorder(BorderFactory.createEtchedBorder()); } }
private void addComponents() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(2, 5, 2, 5); gbc.weightx = 1.0; for (int i = 0; i < labels.length; i++) { add(labels[i], gbc); } }
Hos Computerworld it-jobbank er vi stolte af at fortsætte det gode partnerskab med folkene bag IT-DAY – efter vores mening Danmarks bedste karrieremesse for unge og erfarne it-kandidater.
Som jeg umiddelbart forstår dit spørgsmål vil du gerne have mulighed for at bruge Drag&Drop på et panel der ligger i en JFrame. Hvis det er tilfældet så kan det gøre gennem en MouseAdapter.
Her er et eksempel jeg havde liggende:
ma = (new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { panelMousePressed(evt); }
Jeg har givet mig til at konvertere mit eget fundne eksempel til Netbeans Platform. Så det må jeg hellere lige se, om jeg kan få til at virke i morgen først.
Det eksempel siger, at ikonerne vises i et jPanel, og de trækkes så over på en tegning, som ligger i et andet jPanel. Begge disse jPanels ligger så i et tredje jPanel. Jeg har forstået det sådan, at denne opbygning vist var god, da der så nemmere kan holdes styr på de forskellige data de forskellige steder (?).
Men dit eksempel ser da endnu mere simpelt ud (selvom det jo skal flettes ind i en masse "Netbeans Platform"-kode). Virker dit eksempel (du siger, at du "havde det liggende") ? Kan ikonet også flyttes rundt efter, det er blevet "sat ned" på billedet?
jeg er ikke sikker på jeg forstår hvad du mener med "Netbeans Platform" kode, java er jo java uanset hvilken API du benytter.
Det lyder umiddelbart som om det ville være fornuftet at vælge en eller anden form for Collection til at holde styr på ikonerne osv. Hvis museknappen så slippes indenfor et bestemt interval (X Y værdier) tilføjes JPanel objektet til en Collection, eksempelvis ArrayList. Koden jeg har smidt her virker fint. Dog er den brugt til et simpelt eksempel til skolebrug. Trække et panel rundt på en Frame. Men ganske simpelt at udbygge.
Nej, jeg kendte heller ikke til Netbeans Platform eller dets kode før, jeg begyndte på denne opgave.
Netbeans Platform er en forholdsvis ny konstruktion af java-projekter. "Problemmet" er, at når man opretter et sådant projekt, så kommer der automatisk en del kode. Det er vist opbygget efter MVC-modellen. Og så skal man jo få sin egen kode til at passe ind i de genererede klasser. Man kan vist ikke tilføje sine egne "normale" java-klasser til et sådant projekt. Hvis man kunne, så skulle disse klasser også kaldes fra den eksisterende kode.
Men man kan oprette listeners og diverse andre "kald" inde fra nogle menu-punkter i Netbeans Platform. Så bliver det interessant, om lister-koden her fra dette spørgsmål blot kan sættes direkte ind i Netbeans-koden, eller om det skal modificeres (med diverse kald rundt i systemet).
I mit eget eksempel bliver et ikon også hentet fra et jPanel, bliver gemt i et array, og sættes så ind over det andet jPanel. Nu skal jeg blot se, om jeg kan få det til at virke.
Hmm, nu har jeg forsøgt, at lave de fornødne ændringer. Men det virker ikke. Listeners'ne bliver dog trickered de forskellige steder, som de burde. Men all-in-all virker det ikke.
Jeg har forsøgt at ryde op i min tidligere kode. Og det ser faktisk ganske overskueligt ud. Jeg kan blot ikke gennemskue, hvor jeg mangler de sidste minimale ændringer. Så hvis der er nogle personer herinde, som vil være så elskværdige at prøve at hitte ud af fejlen ved den følgende kode, så vil jeg være meget taknemmelig. I mellemtiden forsøger jeg, at implementere det med danco's kode-eksempel. (applikationen er opdelt, så et primært bagvedliggende jPanel indeholder 2 jPanels. Det ene af disse jPanels skal vise de ønskede ikoner (på labels), som vises ud fra nogle valgt alt efter valg i nogle dropdown-boxes. Det andet jPanel skal så vise et billede, som godtager de førnævnte labels med ikoner, og som tillader flytten rundt på disse labels med ikoner i ovenpå det bagvedliggende billede.)
/** * Top component which displays something. */ @ConvertAsProperties(dtd = "-//org.projekt.window//projekt Window//EN", autostore = false) public final class projekt WindowTopComponent extends TopComponent { //OWN IMPLEMENTATION BEGIN /** * Mouse code to enable image dragging from * ImageSelectionPanel to MainDisplayPanel * both located in SelectablePanel. */
private JLabel[] labels; Image image;
class SelectableAction extends MouseInputAdapter {
javax.swing.JPanel selectablePanel; javax.swing.JPanel imagePanel; javax.swing.JPanel mainPanel; Image selectedImage; boolean dragging; Rectangle r; Point offset; Point p;
public void setImage(Image i) { image = i; }
public void setOrigin(Point p) { this.p = p; repaint(); }
@Override public void mousePressed(MouseEvent e) { Point p = e.getPoint(); JLabel[] labels = getLabels(); for (int i = 0; i < labels.length; i++) { r = labels[i].getBounds(); if (r.contains(p)) { selectedImage = ((ImageIcon) labels[i].getIcon()).getImage(); setImage(selectedImage);//selectablePanel.setImage(selectedImage); offset.x = p.x - r.x; offset.y = p.y - r.y; dragging = true; break; } } }
@Override public void mouseReleased(MouseEvent e) { JLabel label = new JLabel(new ImageIcon(selectedImage)); label.setBorder(BorderFactory.createEtchedBorder()); mainPanel.add(label); Point p = SwingUtilities.convertPoint(selectablePanel, r.x, r.y, mainPanel); label.setBounds(p.x, p.y, r.width, r.height); mainPanel.repaint(); dragging = false; }
@Override public void mouseDragged(MouseEvent e) { if (dragging) { r.x = e.getX() - offset.x; r.y = e.getY() - offset.y; setOrigin(new Point(r.x, r.y));//selectablePanel.setOrigin(new Point(r.x, r.y)); } } } //OWN IMPLEMENTATION END
private void initComponents() {
jPanel4 = new javax.swing.JPanel(); jPanel3 = new javax.swing.JPanel(); jButton1 = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); JLabel[] labels; jPanel2 = new javax.swing.JPanel(); choice1 = new java.awt.Choice(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); choice2 = new java.awt.Choice(); jLabel4 = new javax.swing.JLabel(); jLabel5 = new javax.swing.JLabel(); jLabel6 = new javax.swing.JLabel(); jLabel7 = new javax.swing.JLabel(); choice6 = new java.awt.Choice(); jLabel8 = new javax.swing.JLabel(); textField1 = new java.awt.TextField(); jLabel10 = new javax.swing.JLabel(); jTextField1 = new javax.swing.JTextField(); jTextField2 = new javax.swing.JTextField(); jLabel9 = new javax.swing.JLabel(); jTextField3 = new javax.swing.JTextField(); jTextField4 = new javax.swing.JTextField(); ColorIcon = new javax.swing.JButton(); jLabel11 = new javax.swing.JLabel(); jPanel1 = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel();
resterende initialiseringkode fjernet for overskuelighedens skyld...
}
public JLabel[] getLabels() { return labels; }
SelectableAction action;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: }
private void ColorIconActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: }
private void choice2ItemStateChanged(java.awt.event.ItemEvent evt) { // TODO add your handling code here: if(choice1.getSelectedItem()!=null) { System.out.println("\nText caught\n"); ColorIcon.setText(choice2.getSelectedItem().toString()); } }
private void jPanel1MouseClicked(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("jPanel1MouseClicked in pictureJpanel"); }
Point panelmotionOffset; JLabel panelmotionSelectedLabel; Rectangle panelmotionR; boolean panelmotionDragging;
private void jPanel1MousePressed(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("jPanel1MousePressed in pictureJpanel"); Component[] c=getComponents(); for(int i=0; i<c.length; i++) { if(c[i] instanceof JLabel) { panelmotionR=c[i].getBounds(); Point p=evt.getPoint(); if(panelmotionR.contains(p)) { panelmotionSelectedLabel=(JLabel)c[i]; panelmotionOffset.x=p.x-panelmotionR.x; panelmotionOffset.y=p.y-panelmotionR.y; panelmotionDragging=true; break; } } } }
private void jPanel1MouseReleased(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("jPanel1MouseReleased in pictureJpanel"); panelmotionDragging=false; }
private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("jPanel1MouseDragged in pictureJpanel"); if(panelmotionDragging) { panelmotionR.x=evt.getX()-panelmotionOffset.x; panelmotionR.y=evt.getY()-panelmotionOffset.y; panelmotionSelectedLabel.setBounds(panelmotionR.x, panelmotionR.y, panelmotionR.width, panelmotionR.height); repaint(); } }
Rectangle selectableActionR;
private void formMousePressed(java.awt.event.MouseEvent evt) { // TODO add your handling code here: Point p=evt.getPoint(); System.out.println("formMousePressed in topComponent"); }
private void formMouseClicked(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("formMouseClicked in topComponent");
}
private void formMouseDragged(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("formMouseDragged in topComponent"); if(panelmotionDragging) { panelmotionR.x=evt.getX()-panelmotionOffset.x; panelmotionR.y=evt.getY()-panelmotionOffset.y; panelmotionSelectedLabel.setBounds(panelmotionR.x, panelmotionR.y, panelmotionR.width, panelmotionR.height); repaint(); } } /*already defined??? Point panelmotionOffset; JLabel panelmotionSelectedLabel; Rectangle panelmotionR; boolean panelmotionDragging; */ private void formMousePressed1(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("formMousePressed1 in topComponent"); //action. System.out.println("formMousePressed1 try to implement the mouseAction BEGIN"); //Try to implement the overwritten mouseAction(=action): addMouseListener(action); addMouseMotionListener(action); System.out.println("formMousePressed1 try to implement the mouseAction END"); Component[] c=getComponents(); for(int i=0; i<c.length; i++) { if(c[i] instanceof JLabel) { panelmotionR=c[i].getBounds(); Point p=evt.getPoint(); if(panelmotionR.contains(p)) { panelmotionSelectedLabel=(JLabel)c[i]; panelmotionOffset.x=p.x-panelmotionR.x; panelmotionOffset.y=p.y-panelmotionR.y; panelmotionDragging=true; break; } } } }
private void formMouseReleased(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("formMouseReleased in topComponent"); panelmotionDragging=false; }
private void jPanel2MouseClicked(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("jPanel2MouseClicked in picturepanel. Now attempt of calling MouseClikced in panel behind this panel:"); /* MouseListener[] mouseListenersFromJPanel4=jPanel4.getMouseListeners();//formMouseClicked//formMouseClicked if(mouseListenersFromJPanel4.length!=0){ System.out.println("mouseListenersFromJPanel4.length!=0. Length= "+mouseListenersFromJPanel4.length); for(int index=1; index<mouseListenersFromJPanel4.length+1; index++) { System.out.println("Attempt to call jPanel4.mouseLister from jPanel2MouseClicked"+mouseListenersFromJPanel4[index].toString()); mouseListenersFromJPanel4[index].mouseClicked(evt); } }*/ }
private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) { // TODO add your handling code here: System.out.println("Now trying to implement a listener on the picture:"); //addMouseListener(action); HAVE NO EFFECT //addMouseMotionListener(action); HAVE NO EFFECT }
Nu har jeg forsimplet scenariet en del. Nu er der kun 1 jPanel, hvorpå jeg har oprettet en label med baggrundsbillede, og en label med et ikon. Dette ikon kan jeg nu trække rundt på grænsefladen. Og til at begynde med virkede det også fint. Men af en eller anden grund, så forsvinder ikonet nu, når jeg trækker det hen over baggrundsbilledet. Det kommer dog til syne igen, når jeg trækker det ud fra baggrundsbilledets afgrænsninger igen.
Jeg har forsøgt at finde ud af, og de forskellige elementer kan angives i forskellige lag - altså en z-værdi. For hvis baggrundsbilledet angives i et lavere lag end ikonet, så er problemet sikkert løst. Men jeg kan ikke finde en sådan værdi.
Så det undrer mig, hvad der kan være sket, siden det har virket, men ikke længere gør det optimalt...
Første problem, som jeg ser det, er, at en sådan pane dækker hele GUI'en. Altså også de knapper, som ellers skulle stille funktionalitet til rådighed. Så når man trækker en label rundt, så afskærer man også muligheden for at skabe nye labels (og al anden funktionalitet). Dette kan vel løses ved, at glasspanen kun er aktiv, når musetasten holdes nede. Derved generhverver man muligheden for knappetryk, når man har sluppet musentasten. Men hvad så med den label, man lige har behandlet? Forsvinder den så helt igen, eftersom glasspanen bliver deaktiveret, eller hvilket niveau i dybde ender den på?
Næste problem er, at jeg ikke kan se nogen mulighed for, at man kan oprette en glasspane i Netbeans Platform, eftersom Netbeans tager hånd om skabelsen af alle disse grundliggende elementer. Og man kan ikke gå ind i koden, og rette den til manuelt - for så ville jeg blot foretage ændringerne efter default-initialiseringen af main-pane'en. Ej heller kan jeg finde adgang til at sætte en depth-variabel på labellen (eller andet), hvormed man så kunne styre dens placering.
Jeg er derfor kommet frem til den midlertidige konklusion: eftersom Netbeans Platform sætter vise grænser op for den manuelle kodning, må man gå over til den gammeldags manuelle Swing-kodning. Godt nok bliver teknologien ikke videreudviklet, men hvis dette er det eneste sted, hvor det ønskede er opnåeligt, så må det jo være sådan.
Er det det rigtige at gøre, at skifte til ren swing?
Der skulle vel ikke være nogen, der kan vejlede mig i, om det vil være fornuftigt, at gå over til ren Swing-teknologi og dermed forlade Netbeans Platform?
Vi kommer nok ikke tættere på en løsning af det reele problem, så del-løsningen, som Danco kom med, må være det acceptable. Så hvis du lige lægger et svar, Danco?
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.