Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
D0ll0k
Člen
Avatar
D0ll0k:19.9.2014 19:01

Ahojte :), potřeboval bych poradit s jedním problémem. Mám třídu, ve které vykresluji obrázky. Chci zjistit, na který obrázek jsem klikl a popřípadně ho nahradit nějakým jiným obrázkem nebo i smazat obrázek. Napadlo mě, že bych mohl udělat nějakou instanci obrázku, jenže nevím jak a kde ji napsat. Taky, když dám ty FOR do podmínky, tak se nevykreslí.
Tady jsou třídy:

Hlavní třída:

public class Okno extends JFrame{

        private static final long serialVersionUID = 1L;
        private int sirka = 600;
        private int vyska = 500;

        public Okno() {
                Gui gui = new Gui();
                this.add(gui);

                this.setTitle("Sirky");
                this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                this.setSize(sirka, vyska);
                this.setResizable(false);
                this.setLocationRelativeTo(null);
        }

        public static void main(String[] args) {
                Okno okno = new Okno();
                okno.setVisible(true);
        }
}

Třída, kde vykresluju obrázky:

public class Gui extends JPanel{
        private static final long serialVersionUID = 1L;

        public static Image obrazek1, obrazek2;

        public static boolean klik = false;

        public Gui() {

                Color barva = new Color(44, 224, 180);

                this.setBackground(barva);
                this.addMouseListener(new MouseInput());

                ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));
                ImageIcon ii2 = new ImageIcon(this.getClass().getResource("sirka2.png"));
                obrazek1 = ii1.getImage();
                obrazek2 = ii2.getImage();

        }

        public void paintComponent(Graphics g) {
                super.paintComponent(g);
                int x = 0;

                for(int i = 0; i < 7; i++){
                        g.drawImage(obrazek1, x + 160, 150, this);
                        x += 40;
                }

                x = 0;

                for(int j = 0; j < 8; j++) {
                        g.drawImage(obrazek1, x + 140, 230, this);
                        x += 40;
                }
    }
}

Tady je třída, ve které zjišťuji, na které místo jsem klikl:

public class MouseInput implements MouseListener {

        @Override
        public void mouseClicked(MouseEvent arg0) {

        }

        @Override
        public void mouseEntered(MouseEvent arg0) {

        }

        @Override
        public void mouseExited(MouseEvent arg0) {

        }

        @Override
        public void mousePressed(MouseEvent e) {
                int mx = e.getX();
                int my = e.getY();

                if(mx <= 192 && mx >= 160) {
                        if(my <= 214 && my >= 150) {
                                System.out.println("Pressed");
                        }
                }
        }

        @Override
        public void mouseReleased(MouseEvent arg0) {

        }

}
Editováno 19.9.2014 19:02
Odpovědět
19.9.2014 19:01
Veni, vidi, programmato
Avatar
Atrament
Tvůrce
Avatar
Odpovídá na D0ll0k
Atrament:20.9.2014 19:30

Co třeba ty obrázky zobrazovat pomocí JLabel a pak akorát sledovat MouseEventy na těch JLabelech?

 
Nahoru Odpovědět
20.9.2014 19:30
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:21.9.2014 16:40

Mohl by jsi mi prosím říct jak? Já jsem v tomhle nový.

Nahoru Odpovědět
21.9.2014 16:40
Veni, vidi, programmato
Avatar
Atrament
Tvůrce
Avatar
Odpovídá na D0ll0k
Atrament:21.9.2014 17:19

Tak jeden způsob by mohl třeba vypadat takto:

...

ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));

JLabel label1 = new JLabel(ii1);
label1.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                //Tady bude kód co se spustí po kliknutí...
            }



        });
this.add(label1);

...
 
Nahoru Odpovědět
21.9.2014 17:19
Avatar
xxxvodnikxxx
Člen
Avatar
xxxvodnikxxx:21.9.2014 18:44

Tak pokud by jsi chtěl třídu obrázku, tak si můžeš udělat datový položky např.

  • levej horní roh (Point), pravej dolní roh (Point), danej obrázek (Image / BufferedImage,.. )

Následně by sis mohl udělat např. ArrayList týhle třídy, následně by jsi musel prolejzat tenhle ArrayList a testovat jestli nakliknutej bod patří onomu obrázku nebo ne

Nahoru Odpovědět
21.9.2014 18:44
Unix- svět, kde chcete být nulou :) (UID)
Avatar
jan.janusek
Člen
Avatar
jan.janusek:22.9.2014 10:15

Jednoduché ak som ťa pochopil správne :) síce som moc tvoj kód nečítal ale skús to takto... Vždy keď klikneš myšou vypýtaj si jej polohu na obrazovke, potom použi metódu intersects alebo tak nejako sa to volá majú ju objekty typu rectangle aby vedeli či sa navzájom neprekrývajú a to je ono kliknutím vytvoríš malý virtuálny obdĺžnik a zo súradníc obrázka spravíš druhý a potom ich cez tú metódu porovnáš ak sa prekrývajú tak ho zmažeš to už je na tebe... tu na to majú aj tutoriál tak si ho skús pozrieť tu: http://www.itnetwork.cz/…sovac-kolize

Nahoru Odpovědět
22.9.2014 10:15
Čo si sám nenakódiš nevieš.
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:27.9.2014 13:48

Díky za radu, ale když chci, aby se změnil obrázek, musim ho nastavit na final, jenže pak ho nemůžu zase změnit nazpátek a nebo ho úplně vymazat. Taky bych tímto způsobem musel nastavit všech patnáct obrázků, což není zrovna dvakrát neúspornější.

Nahoru Odpovědět
27.9.2014 13:48
Veni, vidi, programmato
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:27.9.2014 20:35

Tak jsem už vyřešil nastavování obrázků, ale pořád tu zbývá otázka, jak přidat každýmu obrázku MouseEvent.

Nahoru Odpovědět
27.9.2014 20:35
Veni, vidi, programmato
Avatar
Atrament
Tvůrce
Avatar
Odpovídá na D0ll0k
Atrament:28.9.2014 11:57

Tak pokud bys použil mnou navrhované řešení s pomocí JLabel, tak nastavování obrázků se děje pomocí setIcon(). Sice asi nechápu přesně co se snažíš vytvořit, ale pokud má jít o to, že máš zobrazený obrázek a po kliknutí na něj se obrázek vymění za jiný, tak je řešení s JLabel a setIcon imho nejjednodušší - prostě si vytvoříš tolik ImageIcon kolik tam chceš rotovat obrázků, jeden JLabel, kterému dodáš MouseAdapter a který zareaguje na kliknutí tím, že se podívá jaký je zrovna nastaven obrázek (getIcon() na JLabel, který si vytáhneš z eventu pomocí getSource()) a podle toho nastaví jiný obrázek (setIcon() na JLabel).

Následující příklad tak při kliknutí střídá v jednom JLabelu dva obrázky:

...

ImageIcon img1 = new ImageIcon(this.getClass().getResource("img1.png"));
ImageIcon img2 = new ImageIcon(this.getClass().getResource("img2.png"));

JLabel label1 = new JLabel(img1);
label1.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                JLabel clicked = (JLabel) e.getSource();
                if (clicked.getIcon() == img1)
                {
                    label.setIcon(img2);
                }
                else if (clicked.getIcon() == img2)
                {
                    label.setIcon(img1)
                }

            }



        });
this.add(label1);
...
 
Nahoru Odpovědět
28.9.2014 11:57
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na D0ll0k
Jan Vargovský:28.9.2014 21:20

Je to čtvercová (nebo také obdelníková) síť obrázků?

 
Nahoru Odpovědět
28.9.2014 21:20
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:29.9.2014 17:25

Ten tvůj nápad jsem použil. Akorát trochu jinak, protože jak jsi mi doporučil teď ty, hlásí mi to chybu, musim vytvořit metodu add(); Já jsem to napsal takto:

ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));
ImageIcon ii2 = new ImageIcon(this.getClass().getResource("sirka2.png"));
JLabel label = new JLabel(ii1);
boolean clicked = true;

public Sirka(JLabel label) {
        this.label = label;

        label.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                Clicked();
            }
        });
}

public void Clicked() {
        if(clicked == true) {
                label.setIcon(ii2);
        }else {
                label.setIcon(ii1);
        }

        clicked = !clicked;
}

Vše mi funguje. Ve třídě Gui stačí napsat:

ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));
JLabel label1 = new JLabel(ii1);
Sirka sirka = new Sirka(label1);
this.add(label1);

Jediné, co potřebuji je, zjistit jestli se nedá nějakým úsporným způsobem vyřešit vytváření a přidávání těch instancí s JLabelama a následné jejich vložení. Když totiž dám instance a JLabely do FOR() takto, tak to nefunguje:

int c = 0;

for(int i = 0; i < 3; i++){
        String jmeno = "jlabel" + c;
        JLabel jmeno + c = new JLabel(ii1);
        c++;
}
Nahoru Odpovědět
29.9.2014 17:25
Veni, vidi, programmato
Avatar
Atrament
Tvůrce
Avatar
Odpovídá na D0ll0k
Atrament:29.9.2014 19:14
  1. Jaký je smysl toho boolean clicked?

2)

JLabel jmeno + c = new JLabel(ii1);

přece nemůžeš vůbec dělat, proč tam máš to '+ c'? A proč tam vůbeš děláš nějaké 'c' když už tam máš 'i', které se ti inkrementuje?

  1. Proc máš ve tříde Sirka, konstruktor beroucí parametr JLabel, který nastaví 'label' na to co mu předáš parametrem a zároveň v té třídě ten label vytváříš pomocí new?
  2. metoda add(), kterou jsem použil na posledním řádku mého příkladu slouží k vložení toho vytvořeného JLabelu do layoutu, předpokládal jsem, že budeš vytvářet ty JLabely v třídě Okno, která dědí od JFrame, nebo v Gui, která dědí od JPanel, v obou je tudíž tato funkce dostupná. Že tam do toho guláše ještě přihodíš další třídu Sirka, mně nenapadlo :)

Moje rada je, dej si od toho na chvíli pauzu, projdi si znovu tutoriály ohledně vytváření GUI ve Swingu, prostuduj si taky něco ohledně objektového návrhu aplikací a MVC, protože to je ve Swingu velmi důležité, tady na itnetwork je to celkem pěkně všechno vysvětlené. Pak se k tomu vrať, zahoď všechno cos doteď napsal a začni znova :)

 
Nahoru Odpovědět
29.9.2014 19:14
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Jan Vargovský
D0ll0k:29.9.2014 19:55

Je to sedm obrázků nahoře a osm obrázků dole. Přidávám fotku.

Nahoru Odpovědět
29.9.2014 19:55
Veni, vidi, programmato
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:29.9.2014 20:39

Boolean clicked je tam proto, aby jsem mohl vyměňovat obrázky v labelu, protože to jak jsi mi poradil ty, je nějak "zabugované". Když tam vložím dva jlabely s obrázky, kliknu na první obrázek, potom na druhý, a když chci zase na ten první, musim na něj kliknout dvakrát. Právě proto jsem si vytvořil další třídu, která mi zmenšila rozepisování. Jinak bych musel ke každému JLabelu přidat nová MouseAdapter

JLabel jmeno + c = new JLabel(ii1);

U tohoto jsem chtěl při každém cyklu vytvořit nový JLabel, který by se jmenoval jinak. Např. jmeno1, jmeno2, jmeno3.... Já vím, že se to takhle nedělá, jen jsem si chtěl pouze ulehčit práci.
A u metody add(). Potřebuju tam vložit patnáct obrázků s MouseAdapterem a to, že si to dám všechno do jedné třídy mi z toho udělá guláš.

PS: Je to takové krkolomné. Musel bych ti říct do např. telefonu, jak to myslím. Takhle se mi to totiž špatně vysvětluje.

Editováno 29.9.2014 20:41
Nahoru Odpovědět
29.9.2014 20:39
Veni, vidi, programmato
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na D0ll0k
Jan Vargovský:29.9.2014 21:18

I s tím jde pracovat. Jestli jsi teda schopen získat pozici kurzoru, tak na to běž s trochou matiky. Y souřadnici vydělíš polovinou výšky. Přímo na příkladu, když máš výšku 100 a klikneš na Y=30, tak 30/50 = 0 => první řádek. Y=86, 86/50 = 1 => druhý řádek. Tak sámo uděláš i jednotlivé sloupce. Když máš šířku dejme tomu 700 (co 100 pixelů obrázek), tak jen vydělíš X/100 ... protože X je pozice kurzoru od myši a když jí vydělíš 100 (700/100 - celková šířka/šířka jednoho obrázku) tak dostaneš to samé co u toho prvního, třeba klikneš na pozici X = 96, tak 96/100 = 0 => 1. obrázek. X=524 tak 524/100 = 5 => 6. obrázek. Jen třeba někdy uvažovat :)

 
Nahoru Odpovědět
29.9.2014 21:18
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Jan Vargovský
D0ll0k:29.9.2014 23:28

Díky, zkusim to vymyslet. Bude to hodně počítání.

Nahoru Odpovědět
29.9.2014 23:28
Veni, vidi, programmato
Avatar
Atrament
Tvůrce
Avatar
Odpovídá na D0ll0k
Atrament:4.10.2014 14:26

Omluvám se, že reaguju až tak pozdě, měl jsem posledních pár dní moc práce.

Narychlo jsem si teďka zplácal prográmek, co mi zobrazí dvě řady "zápalek", a po kliknutí na kteroukoliv z ní se jí změní stav - pokud je zhasnutá tak se zapálí a naopak (prostě se prohodí dva obrázky.

Docílil jsem toho snadno pomocí JLabel, tak jak jsem navrhoval od začátku. Protože jsem ale nevěděl, že chceš 15 zápalek se stejným chováním, vedl jsem tě směrem k dělání jednoho JLabelu, který by toto obstarával. Pokud chceš těch 15 zápalek, je nejjednodušší způsob si prostě udělat třídu MyLabel, nebo Sirka, tak jak jsi to načal, ale nechat ji dědit od JLabel, a dopsat ji akorát tu svoji funkcionalitu - já jsem tam dopsal akorát metodu switchState(), která prostě přehodí ty obrázky a zavedl jsem proměnnou state, která udržuje stav té zápalky:

public class MyLabel extends JLabel {

    private ImageIcon onIcon = new ImageIcon(this.getClass().getResource("sirka_on.png"));
    private ImageIcon offIcon = new ImageIcon(this.getClass().getResource("sirka_off.png"));

    private Boolean state;

    public MyLabel() {
        setIcon(onIcon);
        state = true; //vytvářená zápalka je na začátku zapálená
        addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                super.mouseClicked(e);
                switchState();
            }
        });

    }

    public void switchState()
    {
        if (state)
        {
            state=false;
            setIcon(offIcon);
        }
        else
        {
            state=true;
            setIcon(onIcon);
        }
    }
}

Všimni si, že jsem teďka v tom MouseAdapteru overridnul mouseReleased() místo mouseClicked() - to řeší ten problém, kdy to někdy nezareagovalo na kliknutí.

S touto třídou vytvořit dvě řady patnácti sirek je otázka jednoho cyklu, například takto:

setLayout(new MigLayout());
        for (int i=0;i<15;i++)
        {
            if (i==6)
            {
                add(new MyLabel(),"wrap");
            }
            else
            {
                add(new MyLabel());
            }
        }
        pack();

Já používám jako layout MigLayout, který vřele doporučuju. Bohužel není součástí Javy takže je ho třeba stáhnout a přidat do knihoven. Ale určitě bys toho výsledku dosáhl i s nějakým klasickým Swingovským layoutem, napadá mně, že GridLayout by mohl být vhodný.

 
Nahoru Odpovědět
4.10.2014 14:26
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:6.10.2014 21:24

Ahoj. Ano přesně takhle jsem to udělal. Akorát jsem, jak jsi radil, použil GridLayout, který se na toto dobře hodí. Později se chystám přidávání jlabelu udělat pomocí pole, aby mohl i počítač odebírat sirky, ale to je už primitivní :)

Nahoru Odpovědět
6.10.2014 21:24
Veni, vidi, programmato
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 18 zpráv z 18.