Avatar
D0ll0k
Člen
Avatar
D0ll0k:

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
Ten, co se snaží "programovat"
Avatar
Atrament
Člen
Avatar
Odpovídá na D0ll0k
Atrament:

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:

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

Nahoru Odpovědět 21.9.2014 16:40
Ten, co se snaží "programovat"
Avatar
Atrament
Člen
Avatar
Odpovídá na D0ll0k
Atrament:

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:

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:

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:

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
Ten, co se snaží "programovat"
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:

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
Ten, co se snaží "programovat"
Avatar
Atrament
Člen
Avatar
Odpovídá na D0ll0k
Atrament:

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ý
Redaktor
Avatar
Odpovídá na D0ll0k
Jan Vargovský:

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:

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
Ten, co se snaží "programovat"
Avatar
Atrament
Člen
Avatar
Odpovídá na D0ll0k
Atrament:
  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:

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
Ten, co se snaží "programovat"
Avatar
D0ll0k
Člen
Avatar
Odpovídá na Atrament
D0ll0k:

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
Ten, co se snaží "programovat"
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na D0ll0k
Jan Vargovský:

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:

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

Nahoru Odpovědět 29.9.2014 23:28
Ten, co se snaží "programovat"
Avatar
Atrament
Člen
Avatar
Odpovídá na D0ll0k
Atrament:

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:

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
Ten, co se snaží "programovat"
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.