[Java]scrollpanes/panels en images probleem.

Pagina: 1
Acties:

  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
Hoi, ik ben een student informatica, en we hebben een opdracht gekregen om een foto applicatie te maken. Het doel is om te leren hoe we design patterns toe moeten passen, daarom eerst even een overzicht van de patterns die in dit programma verwerkt zitten:

Proxy
Model-View-Controller
CommandProcessor
Singleton (De commandprocessor is dat)
Decorator (Om images te resizen tot thumbnails)
ViewHandler (Heb ik nog niet in mijn code gezet)

Als je de applicatie opstart heb je bovenin een splitpane, met links een BrowserView, en rechts een PhotoView. De BrowserView bevat een scrollpane met daarin een JTree. De JTree bevat albums, en albums bevatten foto's. Onderin is er nog een ThumbnailView, met thumbnails erin, maar deze hebben geen invloed op de PhotoView.

De PhotoView was toen het nog werkte een panel, met daarin een foto. Om er voor te zorgen dat bij grote foto's je niet maar een klein stukje ziet heb ik dat panel toen in een scrollpane gezet. Dit werkte erg buggy, omdat de images maar half, of soms helemaal niet in beeld kwamen. Nu heb ik daar dus ook nog een splitpane omheen gezet en nu werkt het helemaal niet meer. (De constructie is dus: splitpane, met daarin: scrollpane, met daarin: panel, met daarin: foto).

Op dit moment geef ik de scrollpane de preferredsize van de foto mee, en als ik dat doe zie ik dat de scrollpane wel de juist dimensies mee krijgt maar dat hij er gewoon geen foto in zet. Als ik de scrollpane een andere preferredsize mee geef tekent hij ook niks in beeld, en krijg ik ook geen scrollbalken te zien.

Als ik debug zijn de variabelen voor zover ik het kan zien wel allemaal goed, dus ik denk toch echt dat er iets in de layout niet helemaal lekker zit. Zou iemand me kunnen helpen met de oplossing? Alles wat ik op internet/GoT vind past volgens mij totaal niet in hoe mijn programma tot nu toe geprogrammeerd is :? Alvast mijn eeuwige dank!

Om het te verduidelijken zet ik hier de code van: PhotoView/PhotoController/AlbumModel.

PhotoView
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class PhotoView extends JPanel implements Observer {
    private static final long serialVersionUID = -4977003466252698238L;
    
    private PhotoController _myController = null;
    private PhotoProxy _photo1 = null;
    private AlbumModel _model = null;
    private JScrollPane _scrollPane;
    
    public PhotoView(){
        this.setLayout(new FlowLayout());
        _photo1 = new PhotoProxy("");
        this.add(_photo1);
        this.setPreferredSize(_photo1.getPreferredSize());
        _scrollPane = new JScrollPane();
        _scrollPane.getViewport().setView(this);
        setVisible(true);
        _scrollPane.setPreferredSize(_photo1.getPreferredSize());
    }
    
    public void initialize(AlbumModel m){
        m.attach(this);
        _model = m;
        _myController = new PhotoController();
        _myController.initialize(m,this);
    }
    
    public void update() {
        
          _photo1 = new PhotoProxy(_model.getCurrentlySelected().get_path());
          this.add(_photo1);
          this.setPreferredSize(_photo1.getPreferredSize());
          _scrollPane.removeAll();
          _scrollPane.setPreferredSize(_photo1.getPreferredSize());
          
          _scrollPane.getViewport().setView(this);
          setVisible(true);
          revalidate();
    
    }
    
    public PhotoProxy getPhoto1() {
        return _photo1;
    }

    public JScrollPane get_scrollPane() {
        return _scrollPane;
    }
    
}


PhotoController
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class PhotoController implements Observer, ActionListener {
    
    AlbumModel _myModel = null;
    PhotoView _myView = null;
    
    public void initialize(AlbumModel m, PhotoView v){
        this._myModel = m;
        this._myView = v;
        
        m.attach(this);
    }

    public void update() {
        // TODO Auto-generated method stub
        
    }

    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
        
    }
}


AlbumModel:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class AlbumModel {
    private ArrayList _observers = new ArrayList();
    private Item _currentlySelected;
    private DefaultMutableTreeNode _currentAlbum;
    
    public void attach(Observer o){
        _observers.add(o);
    }
    
    public void detach(Observer o){
        _observers.remove(o);
    }
    
    /**
     * De aNotify() methode update alle _observers in de arraylist.
     */
    public void aNotify(){
        Iterator itr = _observers.iterator();
        while(itr.hasNext()){
            Observer a = (Observer) itr.next();
            a.update();
        }
    }
    
    public void setCurrentlySelected(Item item) {
        _currentlySelected = item;
        aNotify();
    }

    public Item getCurrentlySelected() {
        return _currentlySelected;
    }
    
    public void setCurrentAlbum(DefaultMutableTreeNode s){
        _currentAlbum = s;
        System.out.println("Huidig album:"+_currentAlbum.toString());
    }
    
    public DefaultMutableTreeNode getCurrentAlbum(){
        return _currentAlbum;
    }

}


De splitpane staat hier niet tussen, die word in de klasse Client aangemaakt, en daar wordt Photoview.get_scrollPane() aan toegevoegd. Mocht je meer klassen willen bekijken qua code dan kan dit, geef het even aan en dan voeg ik die code nog toe. Nogmaals mij dank :)

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
zacht schopje onder z'n kont, niemand die hier een oplossing voor weet? Ik zit er echt helemaal vast mee, heb al vanalles geprobeert met layouts, omdat het schijnt dat Java het snel fout gaat doen als die niet kloppen, maar nog steeds geen succes... :'(

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Als ik je code doorlees zie ik wel dat je doet
Java:
1
2
3
 
_scrollPane = new JScrollPane();
_scrollPane.getViewport().setView(this); 

maar ik zie nergens dat je je JScrollPane aan je JPanel toevoegt.
Overigens kan je ook je foto direct op het JScrollPane zetten door de constructor als volgt te gebruiken:
Java:
1
2
3
JLabel _label = new JLabel(new ImageIcon("heelMooiPlaatje.jpg"));
_scrollPane = new JScrollPane(_label);
// enz, maar je foto moet dan wel een jpg oid zijn. Dat moet je maar willen :)


is dit wat je bedoelt?

  • remyblok
  • Registratie: Oktober 2003
  • Laatst online: 26-03 10:20
Wat volgens mij het probleem is, is dat je telkens _photo1 toe blijft voegen aan de PhotoView en dat die nooit wordt weg gegooid. Je moet is proberen, voordat je een nieuwe PhotoProxy maakt, in je update-method eerst de oude weg kieperen uit de layout. Anders blijft hij daarin zitten. Dus zoiets:

Java:
1
2
3
4
5
6
7
8
9
    public void update() { 
         
          this.remove(_photo1);

          _photo1 = new PhotoProxy(_model.getCurrentlySelected().get_path()); 
          this.add(_photo1); 

         //rest...
    } 

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 00:00
Hogeschool Zeeland, de module Pattern Oriënted Software Engineering :)
Leuke module / opdracht vond ik dat!


Ontopic:

Als ik het mij goed herinner mag je ImageIcon niet gebruiken in deze opdracht cbijlsma, dus het moet wel op een dergelijke manier.
Verder sluit ik me aan bij de twee heren boven mij :)
Trouwens, in je Controller prefix je de members met een underscore en in de initialize() methode gebruik je toch weer keyword this terwijl dat sowieso niet nodig is gezien de naamgeving van de parameters van die methode.

Tip: houdt er alvast rekening mee dat je straks een multiple-document interface moet opleveren.
Afhankelijk van hoe je het een en ander geïmplementeerd hebt kan dat best wel wat gevolgen hebben voor je applicatie.

[ Voor 100% gewijzigd door Kwistnix op 15-01-2006 11:03 ]


  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
Bedankt, ik ga zo eens proberen met jullie tips, moet nu eerst nog even aan een andere opdracht werken + oefenen voor een tentamen van morgen :) Zodra ik resultaten heb post ik het hier wel even.

@cbijlsma Ik had eerst staan:
Java:
1
2
_scrollPane = new JScrollPane();
_scrollPane.getViewport().add(this);


Maar volgens een paar tutorials zou
Java:
1
2
_scrollPane = new JScrollPane();
_scrollPane.getViewport().setView(this);


Hetzelfde doen, dus vandaar dat ik daar wat mee aan het proberen ben geweest, overigens is het zo dat een JPanel een PhotoProxy bevat, en dus niet de scrollpane aan het panel moet worden toegevoegd maar het panel aan de scrollpane.... of maak ik hier nu een grote vergissing?

offtopic:
@fallenangel, er zitten bij ons in de klas 2 mensen die iets van java snappen, de leraar zelf snapt er ook niet alles van en roept alleen "google is your friend young padawan". Ik begin het zelf nu ook nog maar net te begrijpen. Ik denk dus dat als ik dit werkend krijg ik ook zonder een viewhandler wel een voldoende zal krijgen. :)

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 00:00
Ik neem aan dat Edwin deze cursus nog steeds geeft?! Die weet echt wel waar hij mee bezig is hoor! :D

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Volgens het boek dat ik gebruik (Java from the beginning van Jan Skansholm) moet je inderdaad op je JscrollPane een Panel zetten. Maar, probeer eens je PhotoProxy direct op je JScrollPane te zetten.

  • remyblok
  • Registratie: Oktober 2003
  • Laatst online: 26-03 10:20
cbijlsma schreef op zondag 15 januari 2006 @ 19:35:
Volgens het boek dat ik gebruik (Java from the beginning van Jan Skansholm) moet je inderdaad op je JscrollPane een Panel zetten. Maar, probeer eens je PhotoProxy direct op je JScrollPane te zetten.
Als ik in de java-API kijk maakt het niet uit wat je erop zet als het maar iets is wat van java.awt.Component erft. Aangezien je de PhotoProxy kan toevoegem aan een JPanel, waarbij ook een Component ge-add moet worden, is het inderdaaad een idee om de PhotoProxy direct weer te geven in de ScrollPane.
Het JPanel waar de PhotoProxy nu op zit heeft voor de rest toch geen nut, aangezien je er verder niets aan toevoegt.
XyritZz schreef op zondag 15 januari 2006 @ 14:59:
@cbijlsma Ik had eerst staan:
Java:
1
2
_scrollPane = new JScrollPane();
_scrollPane.getViewport().add(this);


Maar volgens een paar tutorials zou
Java:
1
2
_scrollPane = new JScrollPane();
_scrollPane.getViewport().setView(this);


Hetzelfde doen, ...
Klopt. Als je in de broncode kijkt, zie je dat add() uiteindelijk ook setView() aanroept. De uitwerking is dus hetzelfde. Ligt er dus helemaal aan wat je fijn vind. Add() is wat meer standaard imho, al suggereerd het dat er iets (extra) word toegevoegd ipv vervangen.
XyritZz schreef op zondag 15 januari 2006 @ 14:59:
overigens is het zo dat een JPanel een PhotoProxy bevat, en dus niet de scrollpane aan het panel moet worden toegevoegd maar het panel aan de scrollpane.... of maak ik hier nu een grote vergissing?
Wat zeg je hier? :P Op dit moment zie ik het zo: je hebt een PhotoView. Aan PhotoView voeg je een ScrollPane toe. En op dat ScrollPane zit weer een PhotoProxy. Ergens zal je dus dat ScrollPane moeten toevoegen (aan de splitpane?). Je zal dus je ScrollPane zichbaar moeten maken voor de buitenwereld. (corrent me if i'm wrong)
Misschien is het dan een idee om PhotoView van JScrollPane te laten extenden ipv JPanel. Je kan dan direct een PhotoProxy aan de PhotoView toevoegen (setView). En zodra je de PhotoView toevoegt aan je splitpane is het zaakie meteen scrollbaar.

  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
remyblok schreef op zaterdag 14 januari 2006 @ 20:25:
Wat volgens mij het probleem is, is dat je telkens _photo1 toe blijft voegen aan de PhotoView en dat die nooit wordt weg gegooid. Je moet is proberen, voordat je een nieuwe PhotoProxy maakt, in je update-method eerst de oude weg kieperen uit de layout. Anders blijft hij daarin zitten. Dus zoiets:

Java:
1
2
3
4
5
6
7
8
9
    public void update() { 
         
          this.remove(_photo1);

          _photo1 = new PhotoProxy(_model.getCurrentlySelected().get_path()); 
          this.add(_photo1); 

         //rest...
    } 
Misschien is het dan een idee om PhotoView van JScrollPane te laten extenden ipv JPanel. Je kan dan direct een PhotoProxy aan de PhotoView toevoegen (setView). En zodra je de PhotoView toevoegt aan je splitpane is het zaakie meteen scrollbaar.
Ik heb dit beiden gedaan, heb de scrollpane een preferredsize meegegeven zoals ik hem maximaal in mijn programma wil hebben, maar zodra ik een PhotoProxy toe gaan voegen aan het ScrollPane laat hij geen scrollbalken of een foto zien. Ik heb wel setvisible(true); aangeroepen, dus daar kan het niet in zitten.

Ik kom er echt niet meer uit, tijdens debuggen kloppen alle variabelen nog steeds, en worden ze ook goed geupdate als de update methode word aangeroepen, maar om de een of andere reden plaatst hij het geheel gewoon niet goed in een scrollpane :?

Overigens bedankt voor de tip om het meteen van JScrollPane te laten extenden, scheelt weer behoorlijk wat regels code, ziet er een stuk strakker uit nu :)

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
Ik ben er inmiddels achter dat het probleem echt bij de scrollpanes ligt.

Ik heb ook een ThumbnailView, zodra er op een JTree Item geklikt word word van dat album alle foto's in het klein weergegeven. Ik was een beetje met de layout van mijn programma aan het stoeien, en probeerde even die (goed werkende) thumbnails in een scrollpane te plaatsen, en wat zie ik... de thumbnails zijn verdwenen...

Als ik voorbeelden via google zoek werken de meesten met imageicons, maar ik krijg het via mijn Proxy/JPhoto echt niet aan de praat om ze in een scrollpane te krijgen :?

@fallenangel, ik begrijp uit je eerdere reacties dat jij ook aan deze opdracht bezig bent geweest, zou je misschien een hint kunnen geven hoe jij dit opgelost hebt, heb je bijv. nog gebruik gemaakt van een canvas of iets dergelijks?

[ Voor 18% gewijzigd door XyritZz op 16-01-2006 18:29 . Reden: stukje erbij :) ]

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 00:00
Ik weet het niet precies meer, maar volgens mij heb ik een volgende contructie gebruikt:

Ik heb toen MDI geïmplementeerd met een JDesktopPane icm JInternalFrames, dus ieder album had bij mij een eigen JInternalFrame.

Een JInternalFrame bestond uit resp. een JPanel links met een Jtree en wat knopjes d'r in voor naviagatie etc. In het centrum een JPanel voor het laten zien van de (thumbnail decorated) Photo's.
Dat JPanel heb ik toen scrollable gemaakt door het aan een JScrollPane toe te voegen en afhankelijk van wat er weergegeven moest worden heb ik toen een FlowLayout gebruikt voor de normale Photos en een GridLayout voor m'n thumbnails.

Mijn Photo / PhotoProxy / ThumbnailedPhoto waren allemaal subclasses van JComponent als ik het goed heb. Bij het selecteren van een PhotoProxy in de JTree kon ik dus gemakkelijk de removeAll() gebruiken van het rechter JPanel om de huidige photo / thumnails te verwijderen alvorens de nieuwe toe te voegen met add()

Het enige waar je op moet letten is dat je bij het override van de paintComponent() van je Photo / PhotoProxy /Thumbnail als eerste super.paintComponent() aanroept, anders zet ie helemaal niets op het scherm ;)


Viel me trouwens op dat je manier van naamgeven heel erg lijkt op die van mij, met prefixes en volledige variabelenamen, pane ipv panel etc. Is wel leuk om te zien aangezien ik daar toen sterk in afweek ten opzichte van de andere studenten :)

[ Voor 13% gewijzigd door Kwistnix op 16-01-2006 19:43 ]


  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
Ah ok, dat verschilt dus op zo'n substantiele manier van werken met mijn programma dat het dus geen optie meer is om het zo veel om te gaan bouwen, ik ga nog aan de slag met een canvas, heb daar een voorbeeld van gevonden, en als dat niet lukt is het maar jammer.

Uiteindelijk geloof ik dat het grootste deel van de beoordeling is of je de patterns goed hebt toegepast, en het lijkt mij er dan ook niet om te gaan of er wel of geen plaatje in een scrollpane komt.

offtopic:
Ik ben ook de enigste bij mij in de klas die op deze manier programmeert, de code die ik van anderen bekijk vind ik daarom ook verschrikkelijk eruit zien :) Ik heb het gelukkig meteen in het begin al goed geleerd doordat m'n zwager me een paar tips heeft gegeven over naamgeving e.d. :)

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
Nou na weer een paar uur eraan gezeten te hebben ben ik tot het volgende gekomen,

Photoview moet toch een panel zijn, en geen scrollpane.

Door
Java:
1
JScrollPane scrollPane = new JScrollPane(_myPhotoView); 

te gebruiken en dan scrollPane toe te voegen aan mijn splitpane werkt het.
Hiervoor voegde ik aan mijn splitpane _myPhotoView.get_scrollPane(); toe, wat dus niet werkte.

Maar nu komt het, ik krijg wel een foto in beeld, maar de scrollbalken niet. Als ik vervolgens de scrollbalken forceer door

Java:
1
2
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);


Te gebruiken krijg ik wel scrollbalken in beeld, maar zodra er een grote foto is worden ze niet clickable gemaakt. Een preferredSize meegeven aan de scrollpane werkt niet. Kent iemand dit probleem?

[ Voor 9% gewijzigd door XyritZz op 16-01-2006 22:17 . Reden: verduidelijking ]

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • remyblok
  • Registratie: Oktober 2003
  • Laatst online: 26-03 10:20
Staat redelijk duidelijk in de API hoe dit zit.
By default JScrollPane uses ScrollPaneLayout to handle the layout of its child Components. ScrollPaneLayout determines the size to make the viewport view in one of two ways:
  • the view implements Scrollable a combination of getPreferredScrollableViewportSize, getScrollableTracksViewportWidth and getScrollableTracksViewportHeightis used, otherwise
  • eferredSize is used.
Dus aan je PhotoProxy moet je een preferedSize mee geven.


Heb je de tutorial over JScrollPanes al is doorgekeken op de sun site? Misschien werkt het verhelderend. Iig maakt het weinig uit of PhotoView nou van JScrollPane erft of Panel. Kwestie van goed implementeren.

  • XyritZz
  • Registratie: Augustus 2003
  • Laatst online: 16-02 13:52
Het is inmiddels gelukt, ik was bij de PhotoView vergeten de preferredSize aan te passen aan de grootte van de foto die erin staat.

Bedankt voor alle hulp :)

I think there is a world market for maybe five computers. - Thomas Watson (1874-1956), Directeur van IBM (1943)


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 17:17

Robtimus

me Robtimus no like you

Technisch gezien zou je layout manager automatisch zijn preferred size moeten aanpassen aan de foto die erin staat.

Preferred size voor JComponents (JPanels) is in deze volgorde:
  1. De size zoals gezet door setPreferredSize
  2. De preferred size van zijn UI (look n feel) als deze er is
  3. De preferred size van Container
Als er dus geen preferred size is gezet wordt er gekeken naar de UI - deze returned echter null (heb in de source gekeken). Dus Container.

Preferred size van Container is dan:
  1. De preferred size zoals berekend door de layout manager. Voor FlowLayout is dit met 1 component de preferred size van dat ene component.
  2. De preferred size van Component
De preferred size zou dus gewoon de preferred size van je foto moeten zijn.

More than meets the eye
There is no I in TEAM... but there is ME
system specs

Pagina: 1