wxWidgets-Tutorial 014: Überblick Event-Handling

In diesem Video zeige ich grob, wie das Event-Handling funktioniert. Tiefer gehen wir darauf aber dann bei den einzelnen Widgets ein.

Letztlich gibt es drei Varianten, wovon die dritte „deprecated“ ist und nicht mehr in neuen Programmen benutzt werden soll:

  1. Event-Table
  2. Bind
  3. Connect
Überblick über Event-Handling

Ein Screenshot unseres Beispielprogramms.

Screenshot unseres Beispielprogramms

Der Quelltext:

#include <wx/wx.h>

class MyApp : public wxApp {

	public:
		bool OnInit();

};

class MyFrame : public wxFrame {

	public:
		MyFrame();
	
	protected:
		void OnButtonClick(wxCommandEvent &event);

};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit() {
	auto *myFrame = new MyFrame;
	myFrame->Show();

	SetTopWindow(myFrame);

	return true;
}

MyFrame::MyFrame() : wxFrame(nullptr, wxID_ANY, _("Events")) {
	wxButton *button = new wxButton(this, wxID_ANY, _("Click me"));

	button->Bind(wxEVT_BUTTON, &MyFrame::OnButtonClick, this);
}

void MyFrame::OnButtonClick(wxCommandEvent &event) {
	std::cout << "Button clicked" << std::endl;
}

Hier geht es zum Video.

wxWidgets-Tutorial 013: wxGridBagSizer

In diesem Video zeige ich, wie ein wxGridBagSizer funktioniert.

Der wxGridBagSizer basiert auf dem wxFlexGridSizer, bietet aber die Möglichkeit, Widgets und Sizer darin explizit zu positionieren und der Sizer kann Zellen zusammenführen.

Sizer (Layoutmanager): wxGridBagSizer

Hier ein Screenshot von unserem Beispielprogramm:

Screenshot des Beispielprogramms

Der Quelltext:

#include <wx/wx.h>
#include <wx/gbsizer.h>

class MyApp : public wxApp {

	public:
		bool OnInit();

};

class MyFrame : public wxFrame {

	public:
		MyFrame();

};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit() {
	auto *myFrame = new MyFrame;
	myFrame->Show();

	SetTopWindow(myFrame);

	return true;
}

MyFrame::MyFrame() : wxFrame(nullptr, wxID_ANY, _("wxGridBagSizer")) {
	auto *mainPanel = new wxPanel(this);
	
	auto *gridBagSizer = new wxGridBagSizer(5, 5);

	wxGBSpan twoSpan(1, 2);

	gridBagSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Firstname:")), wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_RIGHT);
	gridBagSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxGBPosition(0, 1), twoSpan, wxEXPAND);

	gridBagSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Lastname:")), wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_RIGHT);
	gridBagSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxGBPosition(1, 1), twoSpan, wxEXPAND);

	gridBagSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Age:")), wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_RIGHT);
	gridBagSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxGBPosition(2, 1));

	gridBagSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Zipcode/City:")), wxGBPosition(3, 0), wxDefaultSpan, wxALIGN_RIGHT);
	gridBagSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxGBPosition(3, 1));
	gridBagSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxGBPosition(3, 2), wxDefaultSpan, wxEXPAND);

	gridBagSizer->AddGrowableCol(2);

	mainPanel->SetSizer(gridBagSizer);
	gridBagSizer->SetSizeHints(this);
}

Hier geht es zum Video.

wxWidgets-Tutorial 012: wxSizer verschachteln

In diesem Video zeige ich, wie einfach es ist, wxSizer zu verschachteln.

Um komplexe GUIs zu entwickeln, ist es unabdingbar, dass man Sizer ineinander verschachteln kann. Damit lassen sich einfach und übersichtlich Formulare entwickeln, die dem Benutzer einen hohen Mehrwert bringen.

Sizer (Layoutmanager): wxSizer verschachteln

Hier ein Screenshot unseres Programms:

Screenshot von verschachtelten Sizern

Hier der Quelltext:

#include <wx/wx.h>

class MyApp : public wxApp {

	public:
		bool OnInit();

};

class MyFrame : public wxFrame {

	public:
		MyFrame();

};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit() {
	auto *myFrame = new MyFrame;
	myFrame->Show();

	SetTopWindow(myFrame);

	return true;
}

MyFrame::MyFrame() : wxFrame(nullptr, wxID_ANY, _("Sizer in Sizers")) {
	auto *mainPanel = new wxPanel(this);

	auto *mainBoxSizer = new wxBoxSizer(wxHORIZONTAL);

	auto *flexGridSizer = new wxFlexGridSizer(2, 5, 5);

	flexGridSizer->AddGrowableCol(1);
	flexGridSizer->AddGrowableRow(4);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Firstname:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 0, wxEXPAND);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Lastname:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 0, wxEXPAND);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Zipcode/City:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);

	auto *addressSizer = new wxBoxSizer(wxHORIZONTAL);
	addressSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY));
	addressSizer->AddSpacer(5);
	addressSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 1);

	flexGridSizer->Add(addressSizer, 0, wxEXPAND);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Age:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY));

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Informations:")));
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 0, wxEXPAND);

	mainBoxSizer->Add(flexGridSizer, 1, wxEXPAND | wxALL, 15);

	mainPanel->SetSizer(mainBoxSizer);
	mainBoxSizer->SetSizeHints(this);
}

Hier geht es zum Video.

wxWidgets-Tutorial 011 – wxFlexGridSizer

In diesem Video zeige ich die Verwendung von wxFlexGridSizer.

Im Gegensatz zum wxBoxSizer, der Elemente nur horizontal oder vertikal ausrichten kann, dient der wxFlexGridSizer wie eine Tabelle, in der bestimmt werden kann, welche Spalten und Zeilen sich ausdehen durfen und in dem man einfach Formulare zusammensetzen kann.

Sizer (Layoutmanager): wxFlexGridSizer

Hier ein Screenshot unseres Programms:

Screenshot vom wxFlexGridSizer

Hier der Quelltext:

#include <wx/wx.h>

class MyApp : public wxApp {

	public:
		bool OnInit();

};

class MyFrame : public wxFrame {

	public:
		MyFrame();

};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit() {
	auto *myFrame = new MyFrame;
	myFrame->Show();

	SetTopWindow(myFrame);

	return true;
}

MyFrame::MyFrame() : wxFrame(nullptr, wxID_ANY, _("wxFlexGridSizer")) {
	auto *mainPanel = new wxPanel(this);

	auto *flexGridSizer = new wxFlexGridSizer(2, 5, 5);

	flexGridSizer->AddGrowableCol(1);
	flexGridSizer->AddGrowableRow(3);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Firstname:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 0, wxEXPAND);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Lastname:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 0, wxEXPAND);

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Age:")), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY));

	flexGridSizer->Add(new wxStaticText(mainPanel, wxID_ANY, _("Informations:")));
	flexGridSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), 0, wxEXPAND);

	mainPanel->SetSizer(flexGridSizer);
	flexGridSizer->SetSizeHints(this);
}

Hier geht es zum Video.

wxWidgets-Tutorial 010 – wxBoxSizer

In diesem Video beginnen wir mit Sizern, im Speziellen mit wxBoxSizer.

Layoutmanager sind essentiell bei der Programmierung von grafischen Benutzeroberflächen. Gab es zu Beginn der grafischen Benutzeroberflächen teils nur die Möglichkeit, Elemente absolut positioniert zu platzieren, bieten Layoutmanager, bei wxWidgets Sizer genannt, die Möglichkeit, die Ausrichtung und Anordnung dynamisch zu gestalten.

Der wxBoxSizer kann Elemente horizontal oder vertikal anordnen, proportional vergrößern und verkleiner, ausrichten und vieles mehr.

Sizer (Layoutmanager): wxBoxSizer

Hier ein Screenshot unseres Programms:

Screenshot mit einem wxBoxSizer

Hier der Quelltext:

#include <wx/wx.h>

class MyApp : public wxApp {

	public:
		bool OnInit();

};

class MyFrame : public wxFrame {

	public:
		MyFrame();

};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit() {
	auto *myFrame = new MyFrame;
	myFrame->Show();

	SetTopWindow(myFrame);

	return true;
}

MyFrame::MyFrame() : wxFrame(nullptr, wxID_ANY, _("wxBoxSizer")) {
	auto *mainPanel = new wxPanel(this);
	auto *mainBoxSizer = new wxBoxSizer(wxHORIZONTAL); // wxVERTICAL

	mainBoxSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY, _("Eingabefeld 1")), 1, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 5);
	mainBoxSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY, _("Eingabefeld 2")), 2, wxEXPAND | wxALL, 5);
	mainBoxSizer->AddStretchSpacer();
	mainBoxSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY, _("Eingabefeld 3")), 1, wxEXPAND | wxRIGHT | wxTOP | wxBOTTOM, 5);


	auto *tmp = new wxTextCtrl(mainPanel, wxID_ANY, _("Eingabefeld 0"));
	mainBoxSizer->Insert(0, tmp, 1, wxEXPAND | wxRIGHT | wxTOP | wxBOTTOM, 5);
	mainBoxSizer->InsertSpacer(0, 50);

	mainBoxSizer->Detach(1);
	tmp->Destroy();


	mainPanel->SetSizer(mainBoxSizer);
	mainBoxSizer->SetSizeHints(this);

	std::cout << "Element count: " << mainBoxSizer->GetItemCount() << std::endl;
	std::cout << "Position: " << mainBoxSizer->GetPosition().x << "x" << mainBoxSizer->GetPosition().y << std::endl;
	std::cout << "Size: " << mainBoxSizer->GetSize().GetWidth() << "x" << mainBoxSizer->GetSize().GetHeight() << std::endl;
}

Hier geht es zum Video.

Qt-Tutorial 042: QStatusBar

In diesem Video zeige ich, wie man mit der Statusbar (QStatusBar) umgehen kann.

Viele Fenster des benutzten Fenstermanagers haben am unteren Rand eine Leiste, die manchmal einfach nur da ist, manchmal Informationen anzeigt, manchmal aber auch Interaktionen anbietet. Dieses Video zeigt, wie man Informationen dauerhaft oder für eine gewisse Zeit anzeigt oder Widgets hinzufügt.

QStatusBar

Hier ein Bild unseres Programms:

Screenshot von unserem Beispielprogramm mit QStatusBar

Hier geht es zum Video.

FreeBSD-Grundkurs 033: MySQL für aufbauende Videos installieren

https://youtu.be/o7JoKRrQDkQIch möchte bald ein paar Videos machen, für die wir ein DMBS benötigen. In diesem Video zeige ich, wie man eine einfache (unsichere und für Produktivumgebungen nicht zu verwendende!) MySQL-Datenbank unter FreeBSD (14.2) installieren kann.

FreeBSD-Grundkurs: MySQL für spätere Videos installieren

Die Vorgehensweise

  1. # pkg install mysql90-server
  2. /etc/rc.conf bearbeiten
    • mysql_enable=“YES“
    • mysql_dbdir=“/server/database/mysql“
  3. Verzeichnis erstellen
    • # mkdir -p /server/database/mysql
    • # chown -R mysql:mysql /server/database/mysql
  4. MySQL starten
    • service mysql-server start
  5. Datenbank anlegen
    • mysqladmin create youtube
  6. Benutzer und Berechtigungen erstellen
    • # mysql mysql
    • > CREATE USER ‚youtube’@’%‘ IDENTIFIED BY ‚youtube‘;
    • > GRANT ALL PRIVILEGES ON * . * TO ‚youtube’@’%‘;
    • > FLUSH PRIVILEGES;

Hier geht es zum Video.

FreeBSD-Grundkurs 032: PostgreSQL für aufbauende Videos installieren

Ich möchte bald ein paar Videos machen, für die wir ein DMBS benötigen. In diesem Video zeige ich, wie man eine einfache (unsichere und für Produktivumgebungen nicht zu verwendende!) PostgreSQL-Datenbank (17) unter FreeBSD (14.2) installieren kann.

FreeBSD-Grundkurs: PostgreSQL für spätere Videos installieren

Die Vorgehensweise

  1. pkg install postgresql17-server
  2. /etc/rc.conf bearbeiten
    • postgresql_enable=“YES“
    • postgresql_data=“/server/database/postgres“
    • postgresql_flags=“-w -s -m fast“
    • postgresql_initdb_flags=“–encoding=utf-8 –lc-collate=C“
  3. Datenbankverzeichnis erstellen
    • # mkdir -p /server/database/postgres
    • # chown -R postgres:postgres /server/database/postgres
  4. PostgreSQL initialisieren
    • # service postgresql initdb
  5. Konfigurationen bearbeiten
    • /server/database/postgres/pg_hba.conf
    • /server/database/postgres/postgresql.conf
  6. Datenbankbenutzer erstellen
    • # createuser -s -P youtube
  7. Datenbank erstellen
    • # createdb -O youtube -E unicode

Hier geht es zum Video.

Redmine 5.1 auf FreeBSD

Obwohl es bereits Redmine 6.0.1 zum jetzigen Zeitpunkt gibt, haben wir unter FreeBSD bisher leider „nur“ Version 5.1 zur Verfügung. Allerdings gab es auch eine ganze Weile lang keine lauffähige Redmine-Version für FreeBSD in den Packages und Ports.

Ich habe Version 5.1 testweise in einer VM installiert und es funktionierte problemlos. Letztlich kann man nach dieser Anleitung vorgehen:

Ich freue mich darüber, dass es funktioniert und wir Redmine weiterhin unter FreeBSD nutzen können und hoffe, dass es bald auch eine aktuellere Version gibt.