Qt a wxWidget, kolory i style

0

W qt mamy ekstra style gdzie mozemy dowolnie i latwo modyfikowac kolor, wielkosc, grubosc tekstu czy buttonow.

Ale jak w wxWidget zmienic chocby tlo buttona, czy wielkosc, grubosc tekstu ? w ogole nie moge tego znalezc w dokumentacji...

z gory dzieki za wskazowki

0

wxButton dziedziczy po wxWindow, a tu masz np. metodę SetForegroundColour.

0

no tak, ale:

k->SetForegroundColour((255,123,0));

gdzie k to wskaznik na button (zmienia tylko kolor tekstu na buttonie)
pozostale wersje SetBackgroundColour i dwie analogiczne z "Own" w nazwie w ogole nic nie zmieniaja

0

Nie zmieniają, bo nie zawsze natywne kontrolki dają taką możliwość.

0

ok, no ale jak chce w jakis sposob zmienic kolory buttonow, plansz, tekstu itp. ?

to jak to moge wykonac ? (jak to nie dziala)

0

Jeśli chodzi o przyciski, to nie sądzę, żebyś coś tu zrobił, poza oczywiście napisaniem własnej wersji buttona. Co do pozostałych rzeczy, to raczej nie powinno być problemu.

0

dzieki, a jak można napisac wlasna wersje buttona ? (wyjasnij prosze choc tak w telegraficznym skrocie :) )

0

Tworząc klasę pochodną od wxControl lub wxWindow. Robisz obsługę zdarzeń wxEVT_PAINT i wxEVT_LEFT_DOWN, i wszystko ;)

0

no ok, jak zrobic obsluge tych zdarzen to jeszcze nie wiem za bardzo o co chodzi, no ale nawet jakbym to zrobil, to jakim cudem to wszystko spowoduje ze bede mogl zmieniac kolory ?

0

A potemu kierez,że sam jako obsługę zdarzenia wxEVT_PAINT będziesz sobie malował prostokąt tła o kolorze jaki tylko będziesz sobie życzył,a następnie wywoływał odziedziczoną obsługę tego komunikatu,która domaluje resztę.(Czy nie zamaże Twojego tła musisz obadać)
Generalnie coś jak reimplementacja paintEventa z Qt ;)

0

nie wiem w ogole jak sie za to zabrac ;(

jakby sie komus nudzilo, to podajcie choc zaryhs tego albo jakis w miare kompletny przyklad ;)

z gory wielkie dzieki

0

Masz tu wstęp do klasy przycisku:

class wxMyButton : public wxControl
{
private:

	void on_paint(wxPaintEvent&);
	void on_mouse_down(wxMouseEvent&);
	void on_mouse_up(wxMouseEvent&);
	void on_lost_mouse_cap(wxMouseCaptureLostEvent&);
	void on_size(wxSizeEvent&);

	DECLARE_EVENT_TABLE();

	wxString	m_label;
	bool		m_pressed;

public:
	wxMyButton(wxWindow *parent,
				wxWindowID id,
				const wxString& label = wxT(""),
				const wxPoint& pos = wxDefaultPosition,
				const wxSize& size = wxDefaultSize)
				:wxControl(parent, 
							id, 
							pos, 
							size, 
							0, 
							wxDefaultValidator, 
							wxT("wxMyButton")),
				m_label(label), m_pressed(false)
	{
	}
};

/* plik CPP */

BEGIN_EVENT_TABLE(wxMyButton,wxControl)
	EVT_PAINT(wxMyButton::on_paint)
	EVT_LEFT_DOWN(wxMyButton::on_mouse_down)
	EVT_LEFT_UP(wxMyButton::on_mouse_up)
	EVT_MOUSE_CAPTURE_LOST(wxMyButton::on_lost_mouse_cap)
	EVT_SIZE(wxMyButton::on_size)
END_EVENT_TABLE()


void wxMyButton::on_paint(wxPaintEvent &e)
{
	wxPaintDC dc(this);
		
	wxRect rc = this->GetSize();

	/* odmalowanie tła */
	dc.SetBrush(m_pressed ? *wxRED_BRUSH : GetBackgroundColour());
	dc.DrawRectangle(rc);

	/* ... i tekstu */
	wxSize s = dc.GetTextExtent(m_label);
	wxPoint pt((rc.GetWidth() - s.x) / 2, (rc.GetHeight() - s.y) / 2);
	pt += rc.GetTopLeft();

	dc.SetTextForeground(GetForegroundColour());
	dc.DrawText(m_label, pt);
}

void wxMyButton::on_size(wxSizeEvent&)
{
	Refresh();
}

void wxMyButton::on_mouse_down(wxMouseEvent&)
{
	m_pressed = true;
	Refresh();
	CaptureMouse();
}

void wxMyButton::on_mouse_up(wxMouseEvent &ev)
{
	if(!m_pressed)return;
	m_pressed = false;
	Refresh();
	ReleaseMouse();

	if(GetClientRect().Contains(ev.GetPosition()))
	{
		wxCommandEvent e(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
		e.SetEventObject(this);
		ProcessEvent(e);
	}
}

void wxMyButton::on_lost_mouse_cap(wxMouseCaptureLostEvent&)
{
	m_pressed = false;
	Refresh();
}

--- dodane ---

Dobra, przeedytowałem nieco kod, coby bardziej w zachowaniu przypominał przycisk, a nie np. wxStaticText.

0

ok, dzieki wielkie

pierwsze pytanie: skad Ty wiedziales jak to zrobic ? (jak mozna sie czegos takiego nauczyc ?)

ok, a teraz jak chcialbym dopisac do tego np. metode SetLabel(), to po prosty musze tu dopisac do tej klasy ta metode (bo Ty rozpisales te rozne zdarzenia co sie ma dziac z kliknieciem itp)

0

bo np. u mnie taki kod:

void MyFrame::Clicked(wxCommandEvent& e)
{
	wxMyButton *k = reinterpret_cast<wxMyButton*>(e.GetEventObject());


	int licz = e.GetId();
	

	if (k->GetLabel() == _("X") || k->GetLabel() == _("O"))
		return;

	int znak;

	if (jud.czy_teraz_krzyzyk() == true)
    {
		k->SetForegroundColour(wxColour(0,0,255));
		
		k->SetLabel(_("X"));


...
 

czyli musze do tej nowe klasy wxMyButton dopisac te settery i gettery jakos ?

0

bo u mnie jest tak, ze mam w MyFrame, gridowy layoutu zawierajacy tablice[20[20] takich buttonow, na ktorych robie przerozne operacje, rysuje, zmieniam ich kolor, powiekszam te buttony, zmniejszam.

0

Jeśli chodzi o SetLabel, to pisać tej metody nie musisz, ponieważ jest ona dziedziczona po wxControl. Jedyne co musisz zrobić, to wywalić m_label, zmienić w konstruktorze na:

wxMyButton(wxWindow *parent,
                                wxWindowID id,
                                const wxString& label = wxT(""),
                                const wxPoint& pos = wxDefaultPosition,
                                const wxSize& size = wxDefaultSize)
                                :wxControl(parent, 
                                                        id, 
                                                        pos, 
                                                        size, 
                                                        0, 
                                                        wxDefaultValidator, 
                                                        wxT("wxMyButton")),
                                m_pressed(false)
{
        SetLabel(label); // <--- 
}

i w on_paint:

 wxRect rc = this->GetClientSize(); // <--- przy okazji to zamiast 'GetSize'

...

wxSize s = dc.GetTextExtent(GetLabel());
...
dc.DrawText(GetLabel(), pt);

Klasę tę pisałem na szybko, więc nie pamiętałem o tego typu rzeczach. Pewnie jeszcze jakieś sprawy powyłażą, no ale to już sam powinieneś sobie poprawić.

Odnośnie pierwszego pytania. Odpowiedź klasyczna: dokumentacja + samodzielne eksperymentowanie ;)

0

ok, no bede kombinowal z tym, bo teraz to co robie nabralo jako takiego wygladu :)

gdy w metodzie MyFrame zrobie cos takiego:

tab[i][j + 1].but->SetLabel(_("I"));

to nie pojawi sie ta etykieta na planszy, pojawi sie dopierow po kliknieciu w to pole, jak porpawic, by poijawila sie automatycznie ?

0

ok, napisalem metode w myframe odswiezajaca cala tablice

ale jednego jeszcze nie wiem, przekazywanie rozmiaru tych buttonow do tego konstruktora wxMyButton nie dziala (zawsze maja caly czas staly, za duzy rozmiar)

0

(...) to nie pojawi sie ta etykieta na planszy, pojawi sie dopierow po kliknieciu w to pole (...)

Wydawało mi się, że SetLabel wymusi odmalowanie okna, jak widać nie robi tego. Dorzuć metodę:

void SetLabel(const wxString &label)
{
	wxControl::SetLabel(label);
	Refresh();
}

I powinno być git.

przekazywanie rozmiaru tych buttonow do tego konstruktora wxMyButton nie dziala

U mnie działa bez problemu.

0

rzeczywiscie, ladniej tak zrobic to Refresh

fragment metody tworzacej buttony:

...
size = new wxSize(wielkosc,wielkosc);  //co tu nie dam, mam caly czas iodentyczne buttony
	int wxId = 1000;
	for (int i=0; i<k; ++i)
	{
		//s->AddGrowableCol(i,0);
		//s->AddGrowableRow(i,0);
		for (int j=0; j<k; ++j)
		{
			tab[i][j].but = new wxMyButton(p, wxId, wxEmptyString, wxDefaultPosition, *size);


....
			 
0

Jeśli dodajesz to do jakiegoś sizera, a tak mi się wydaje, to pewnie tu jest problem.

p.s. po co tworzysz size na stercie?

0

no tak, bez sensu to na stercie robic

racja, dodaje wszystko do s = new wxFlexGridSizer(k,k,0,0);

ale dlaczego to powoduje problem ?

0

Może inaczej. Powiedz, co Ty chcesz zrobić z tymi przyciskami, co to ma być.

0

to jest taka duza plansza (20x20 (k=20))
poczatkowo myslalem, zeby zrobic layout, ktory bedzie powiekszal przyciski wraz ze wzrostem okna (z zachowaniem ich kwadratowego ksztaltu)

ale nie wiedzialem jak to zrobic, wiec wpadlem na pomysl dodania wszystkiego do flexgridsizera i zrobienia metod powiekszajacych i pomniejszajacych plansze

0

No to wxGridSizer bardziej tu pasuje.

Przyciski dodajesz z opcją wxEXPAND:

s->Add(btn, 0, wxEXPAND);
0

ale teraz przyciski sa splaszcone (nie kwadratowe) i nie przylegaja idealnie do siebie

w wxFleGridSizer

mialem jeszcze takie cos:

p->SetSizer(s);
s->Fit(this);
s->SetSizeHints(this);

to zapewnialo mi kwadratowy ksztalt i przyleganie

0

Nie wiem o czym piszesz.

Może tak spróbuj:

wxGridSizer* gs = new wxGridSizer(20);

for(int i = 0; i < 20 * 20; ++i)
{
	wxMyButton* btn = new wxMyButton(panel, 
								wxID_ANY, 
								wxString::Format(wxT("%i"), i));
	gs->Add(btn, 0, wxEXPAND);
}

wxBoxSizer* bs = new wxBoxSizer(wxHORIZONTAL);
bs->Add(gs, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxSHAPED);

panel->SetSizer(bs);
panel->Fit();

Opcja z wxBoxSizer'em jest zbędna, jeśli okno ma odpowiednie proporcje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1