QTableView HeaderZellen mit unterschiedlichem Layout

Alles rund um die Programmierung mit Qt
Antworten
YouB
Beiträge: 9
Registriert: 7. August 2008 14:11

QTableView HeaderZellen mit unterschiedlichem Layout

Beitrag von YouB »

Hallo,

ich habe einer QTableView ein Model zugewiesen. Im Model habe ich die headerData() Methode überschrieben. Wie kann ich jetzt abhängig von bestimmten Zeilen im Model den Hintergrund und die Schrift einer Header-Zelle manipulieren. headerData() scheint mir dafür nicht benutzbar, da der Return-Wert ein QVariant ist.

Gruß,
Udo
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

1. Warum soll QVariant nen problem sein ? es kann doch auch Farben(QColor), Schriftarten (QFont) usw adaptieren

2. headerdata() ist ned der rechte ort, wenn es um die zellen geht. headerdata ist fuer die grauen beschriftungen an den seiten der zellen zustaendig. fuer die zellen selber gibts die data methode.

und schau dir bei der data methode mal den "role" Parameter genauer an .... Ansonsten lies mal in der docu bissi genauer ueber das MVC nach, da wird das eigentlich gut erklaert .

Ciao ...
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Eben, weil es ein QVariant ist, kannst du jeden Datentypen zurückgeben. Auch QColor und QFont.
YouB
Beiträge: 9
Registriert: 7. August 2008 14:11

Beitrag von YouB »

Hi,
danke für die Infos.

@RHBaum: Vielleicht habe ich undeutlich ausgedrückt. Ich möchte bei bestimmten Zeilen genau die "grauen beschriftungen an den seiten" andersarbig und mit fetter Schrift hervorheben.

Ich habe bisher immer nur Strings und Zahlenwerte als QVariant zurückgegeben.

Was für ein Objekt kann ich denn nehmen wenn ich möchte dass ein Text in einer Header-Zelle (also diese Zellen an der Seite) in Fett und der Hintergrund nicht grau sondern in einer anderen Farbe dargestellt wird?

Gruß,
Udo
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Was für ein Objekt
Du hasst ned die Wahl des Objectes, du musst nen QVariant zurueckgeben

der Variant hat aber so nen Konstruktor
QVariant ( int typeOrUserType, const void * copy )

und fuer type ist folgendes definiert:
QVariant::Font; 64; a QFont;

was wo und wann zurueckgegeben wird, wird bei headerdata ueber die role und die Ausrichtung definiert ...

Und noch was, das klingt jetzt sicher hart:

Aber in der Doku und bei den Exemples iss alles dabei was man fuer dein Problem braucht. Man muss nur nen kleinwenig modifizieren, abstrahieren kombinieren.
Wenn man das ned kann, bzw ned gewillt ist, dokus zu lesen und sich vorhandene Beispiele anzuschauen, der sollte die Finger vom programmieren lassen !

Ciao ...
YouB
Beiträge: 9
Registriert: 7. August 2008 14:11

Beitrag von YouB »

Ähm,
sorry, aber wie kommst du darauf ich würde die doku, oder die examples mir nicht ansehen?
In den examples (addressbook, editabletreemodel, simpledommodel, simpletreemodel) werden lediglich QString-Objekte zurückgegeben, die natürlich implizit in ein QVariant umgewandelt werden. Im pixelator wird im Fall Qt::SizeHintRole ein QSize-Objkt zurückgegeben (ebenfalls implizit konvertiert).
Ich dachte meine Frage ist für Experten einfach zu beantworten, da ich sicher nicht der erste bin, der so etwas machen möchte. Aber mit der Antwort lies die Doku und schau dir die Examples an, ist das etwas sehr pauschal.
Trotzdem Danke für die Zeit.
Mein aktueller Code sieht so aus:
QVariant BMS_Configuration_Model::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal)
return "Value";
else
{
QString name = m_gui_data_converters.at(section)->get_label();
name += m_gui_data_converters.at(section)->get_unit();
return name;
}
}
return QVariant();
}


Meine Frage ist nach wie vor, wie kann ich beeinflussen, dass bei manchen Zeilen der Text fett und der Hintergrund andersfarbig wird?
Mit dem Konstructor QVariant ( int typeOrUserType, const void * copy ) kann ich für mein Problem nicht soviel anfangen, bzw. ich komme nicht darauf, wie mir das helfen soll. Aus der Beschreibung:
Usually, you never have to use this constructor, use qVariantFromValue() instead to construct variants from the pointer types represented by QMetaType::VoidStar, QMetaType::QObjectStar and QMetaType::QWidgetStar.
Was mit
QVariant::Font; 64; a QFont;
gemeint ist, bleibt mir leider auch verschlossen.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

sorry, aber wie kommst du darauf ich würde die doku, oder die examples mir nicht ansehen?
dann trifft der andere Fall auf dich zu ???

Zu deinem Code:
Ich hab Dir gesagt (bevor ich so ausfaellig geworden bin), du sollst dir den role Parameter bei dem headerdata Aufruf genauer anschauen.
Trotzdem reagierst Du immer nur noch auf die Rolle fuer den anzuzeigenden Text.
Sorry wie soll man da helfen ???
Was mit
QVariant::Font; 64; a QFont;
gemeint ist, bleibt mir leider auch verschlossen.
Das ist nen auszug aus der Doku zu QVariant, und zwar ne ziemlich relevante Stelle fuer Dein Problem.
Da du aber selber die Doku gelesen hasst (behauptest), muessen wir davon ausgehen das du es nicht verstehst. Ok ...
stellt sich weiterhin die frage, was dir fuer das Verstaendniss der Doku fehlt. C/C++ Grundlagen oder liegts am englisch ?
enum Qt::ItemDataRole
Each item in the model has a set of data elements associated with it, each with its own role. The roles are used by the view to indicate to the model which type of data it needs.
The general purpose roles are:

Constant
Value
Description
Qt::DisplayRole
0
The key data to be rendered (usually text).
Qt::DecorationRole
1
The data to be rendered as a decoration (usually an icon).
Qt::EditRole
2
The data in a form suitable for editing in an editor.
Qt::ToolTipRole
3
The data displayed in the item's tooltip.
Qt::StatusTipRole
4
The data displayed in the status bar.
Qt::WhatsThisRole
5
The data displayed for the item in "What's This?" mode.
Qt::SizeHintRole
13
The size hint for the item that will be supplied to views.

Roles describing appearance and meta data:

Constant
Value
Description
Qt::FontRole
6
The font used for items rendered with the default delegate.

Qt::TextAlignmentRole
7
The alignment of the text for items rendered with the default delegate.
Qt::BackgroundRole
8
The background brush used for items rendered with the default delegate.

Qt::BackgroundColorRole
8
This role is obsolete. Use BackgroundRole instead.
Qt::ForegroundRole
9
The foreground brush (text color, typically) used for items rendered with the default delegate.

Qt::TextColorRole
9
This role is obsolete. Use ForegroundRole instead.
Qt::CheckStateRole
10
This role is used to obtain the checked state of an item (see Qt::CheckState).

Accessibility roles:

Constant
Value
Description
Qt::AccessibleTextRole
11
The text to be used by accessibility extensions and plugins, such as screen readers.
Qt::AccessibleDescriptionRole
12
A description of the item for accessibility purposes.

User roles:

Constant
Value
Description
Qt::UserRole
32
The first role that can be used for application-specific purposes.
was ist daran unverstaendlich ?

Ciao ....
YouB
Beiträge: 9
Registriert: 7. August 2008 14:11

Beitrag von YouB »

Ok, den Hinweis
schau dir bei der data methode mal den "role" Parameter genauer an
hatte ich nicht genau verstanden.

Habe den Code jetzt so erweitert:

Code: Alles auswählen

QVariant BMS_Configuration_Model::headerData(int section, Qt::Orientation orientation, int role) const
{
	if (role == Qt::FontRole &&
		orientation == Qt::Vertical &&
		m_gui_data_converters.at(section)->has_label_only())
	{
		QFont font;
		font.setBold(true);
		return QVariant(font);
	}
	if ((role == Qt::BackgroundRole || role == Qt::BackgroundColorRole) &&
	    orientation == Qt::Vertical &&
	    m_gui_data_converters.at(section)->has_label_only())
	{
		QColor blue(6,255,255);
		return QVariant(67, &blue);
	}
    if (role == Qt::DisplayRole)
    {
        if (orientation == Qt::Horizontal)
            return QVariant("Value");
        else
        {
			QString name = m_gui_data_converters.at(section)->get_label();
			name += m_gui_data_converters.at(section)->get_unit();

			return QVariant(name);
		}
	}
	return QVariant();
}
Das mit dem font in fett klappt, das mit der Hintergrundfarbe leider gar nicht.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Code: Alles auswählen

QVariant BMS_Configuration_Model::headerData(int section, Qt::Orientation orientation, int role) const
{
   if (role == Qt::FontRole &&
      orientation == Qt::Vertical &&
      m_gui_data_converters.at(section)->has_label_only())
   {
      QFont font;
      font.setBold(true);
      return QVariant(font);
   }
   if ((role == Qt::BackgroundRole || role == Qt::BackgroundColorRole) &&
       orientation == Qt::Vertical &&
       m_gui_data_converters.at(section)->has_label_only())
   {
      QColor blue(6,255,255);
      return QVariant(67, &blue);
   }
    if (role == Qt::DisplayRole)
    {
        if (orientation == Qt::Horizontal)
            return QVariant("Value");
        else
        {
         QString name = m_gui_data_converters.at(section)->get_label();
         name += m_gui_data_converters.at(section)->get_unit();

         return QVariant(name);
      }
   }
   return QVariant();
}
sieht doch scho nen Stueck besser aus !

Code: Alles auswählen

     QFont font;
      font.setBold(true);
      return QVariant(font);
besser: den Orginal font vom basis - model holen undd ann modifizieren, dann gehen die einstellungen ausm designer ned verloren

Code: Alles auswählen

     QVariant var = QAbstractItemModel::headerData(section, orientation, role);
     if(var.isValid ())
     {
           QFont origFont = var.value();
           origFont.setBold(true);
           varreturn = origFont;  /// QFont hat einen operator QVariant () const ! 
     }
Qt::BackgroundRole langt zu implentieren... BackgroundColorRole wird als obsolete gemarkt ... also ned benutzen ! (is nur fuer rueckwartskompatbilitaet.

Weiterhin .....
The background brush used for items rendered with the default delegate.
Also nicht nur die farbe, sondern der komplette Pinsel (Brush).

Nach dem selben prinzip:

Code: Alles auswählen

  if ((role == Qt::BackgroundRole) &&
       orientation == Qt::Vertical &&
       m_gui_data_converters.at(section)->has_label_only())
   {
 QVariant var = QAbstractItemModel::headerData(section, orientation, role);
     if(var.isValid ())
     {
           QBrush origbrush = var.value();
           origbrush.setColor(QColor(6,255,255));
           varreturn = origbrush;  /// auch QBrush hat einen operator QVariant () const ! 
     }
   }
Ciao ...
YouB
Beiträge: 9
Registriert: 7. August 2008 14:11

Beitrag von YouB »

Oh danke und interessant mein Code hat sich in dieselbe Richtung entwickelt, das mit dem Brush habe ich auch benmerkt.
Hatte mir den Code von qheaderview.cpp angesehen und davon geklaut. Daher das mit dem CanConvert und cast. Allerdings läuft der code immer in den else Teil und nicht in den Teil mit orig_font, bzw. orig_brush. Der hintergrund ist aber leider immer noch nicht blau.
Was mache ich da falsch, bzw. wo könnte ich da nachschauen? Durchlaufen wird der Code bei dem es um die BackgroundRole geht definititv.

Mein aktueller code sieht so aus:

Code: Alles auswählen

QVariant BMS_Configuration_Model::headerData(int section, Qt::Orientation orientation, int role) const
{
	QVariant return_var;

	if (role == Qt::FontRole &&
		orientation == Qt::Vertical &&
		m_gui_data_converters.at(section)->has_label_only())
	{
		QVariant font_var = QAbstractItemModel::headerData(section, orientation, role);
		if (font_var.isValid() && qVariantCanConvert<QFont>(font_var))
		{
			QFont orig_font = qvariant_cast<QFont>(font_var);
			orig_font.setBold(true);
			return_var = orig_font;
		}
		else
		{
			QFont font;
			font.setBold(true);
			return_var = font;
		}
	}
	else if (role == Qt::BackgroundRole &&
	         orientation == Qt::Vertical &&
	         m_gui_data_converters.at(section)->has_label_only())
	{
		QVariant brush_var = QAbstractItemModel::headerData(section, orientation, role);
		if (brush_var.isValid() && qVariantCanConvert<QBrush>(brush_var))
		{
			QBrush orig_brush = qvariant_cast<QBrush>(brush_var);
			orig_brush.setColor(QColor(6,255,255));
			return_var = orig_brush;
		}
		else
		{
			QBrush blue_brush(QColor(6,255,255));
			return_var = blue_brush;
		}
	}
	else if (role == Qt::DisplayRole)
    {
        if (orientation == Qt::Horizontal)
            return QVariant("Value");
        else
        {
			QString name = m_gui_data_converters.at(section)->get_label();
			name += m_gui_data_converters.at(section)->get_unit();

			return_var = name;
		}
	}
	return return_var;
}
Leider scheidert das mit der Hintergrundfarbe immer noch. Hatte schon verschiedene Varianten probiert.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Muss mal probieren ob das ueberhaupt geht ....
kannst du mal debuggen, ob du fuer headerdata ueberhaupt nen aufruf fuer die backgroundrole bekommst ?

Die Frage ist, warum will man ueberhaupt die hintergrundfrage der zeilenueberschriften aendern will, weil die sind ja quasi in ner 3d anzeige (Buttonstyle), keine ahnug was genau der da malt und wo er die farben fuer die schatten und vertiefungen etc herbekommt.


Ciao ...
YouB
Beiträge: 9
Registriert: 7. August 2008 14:11

Beitrag von YouB »

Hallo,

also headerData wurde mit BackgroundRole aufgerufen. Hat allerdings nicht die Farbe verändert.

Ich wollte die HintergrundFarbe verändern, um einzelne Abschnitte bei einer langen Liste von Einträgen farblich abzusetzen.

Habe das ganze jetzt so gelöst, dass ich auf den vertical header komplett verzichte. Ich habe eine Spalte hinzugefügt und die Einträge um eine Spalte verschoben. Nun nehme ich die erste Spalte (also die nullte) als eigenen vertical header. Bei der data-Methode funktioniert das mit der BackgroundRole wunderbar.

Nochmal vielen Dank für die Unterstützung.

Gruß
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Habe das ganze jetzt so gelöst, dass ich auf den vertical header komplett verzichte. Ich habe eine Spalte hinzugefügt
Macht IMHO auch mehr Sinn .... weil die Zeilen und Spaltenheader wirklich nur fuer die darstellungsneutralen Markierungen sind ... ala die Zeilen und Spalten Markierungen wie bei Excel / Calc, und damit eher vom GUI Style als von den Daten abhaengig sein sollten.
Denk mal deswegen wird das wahrscheinlich auch ueberschrieben ....

Ciao ...
Antworten