Ci sono una serie di domande scritte sulla limitazione di QSpinBox dell'uso di un int come suo tipo di dati. Spesso le persone vogliono mostrare numeri più grandi. Nel mio caso, voglio essere in grado di mostrare un numero intero a 32 bit senza segno in esadecimale. Ciò significa che mi piacerebbe che il mio intervallo fosse [0x0, 0xFFFFFFFF]. Il più grande QSpinBox normale può andare è 0x7FFFFFFF. Rispondendo alla mia domanda qui, la soluzione che ho trovato è quella di forzare semplicemente l'int a essere trattato come un int unsigned, reimplementando le relative funzioni di visualizzazione e validazione.QSpinBox con unsigned int per ingresso esadecimale
risposta
Il risultato è piuttosto semplice e funziona bene. Condivisione qui nel caso in cui qualcun altro possa beneficiare di questo. Ha una modalità a 32 bit e una modalità a 16 bit.
class HexSpinBox : public QSpinBox
{
public:
HexSpinBox(bool only16Bits, QWidget *parent = 0) : QSpinBox(parent), m_only16Bits(only16Bits)
{
setPrefix("0x");
setDisplayIntegerBase(16);
if (only16Bits)
setRange(0, 0xFFFF);
else
setRange(INT_MIN, INT_MAX);
}
unsigned int hexValue() const
{
return u(value());
}
void setHexValue(unsigned int value)
{
setValue(i(value));
}
protected:
QString textFromValue(int value) const
{
return QString::number(u(value), 16).toUpper();
}
int valueFromText(const QString &text) const
{
return i(text.toUInt(0, 16));
}
QValidator::State validate(QString &input, int &pos) const
{
QString copy(input);
if (copy.startsWith("0x"))
copy.remove(0, 2);
pos -= copy.size() - copy.trimmed().size();
copy = copy.trimmed();
if (copy.isEmpty())
return QValidator::Intermediate;
input = QString("0x") + copy.toUpper();
bool okay;
unsigned int val = copy.toUInt(&okay, 16);
if (!okay || (m_only16Bits && val > 0xFFFF))
return QValidator::Invalid;
return QValidator::Acceptable;
}
private:
bool m_only16Bits;
inline unsigned int u(int i) const
{
return *reinterpret_cast<unsigned int *>(&i);
}
inline int i(unsigned int u) const
{
return *reinterpret_cast<int *>(&u);
}
};
Il tuo 'reinterpret_cast's viola [strict alasing rule] (http://eel.is/c++draft/basic.lval#8). Quindi il codice contiene UB – yrHeTaTeJlb
mi si avvicinò con lo stesso problema, ma utilizzando PyQt quindi non ho potuto evitare la gamma controllando che Qt stava facendo in C sotto il cofano.
La soluzione alternativa era utilizzare un QDoulbeSpinbox e trasmettere il valore a un int in textFromValue.
Ecco il mio codice (implementa anche un menu del tasto destro per cambiare la base di visualizzazione):
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future_builtins import *
import re
import sys
from PyQt4.QtCore import (QRegExp, Qt)
from PyQt4.QtGui import (QApplication, QRegExpValidator, QDoubleSpinBox)
from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
from PyQt4 import QtCore, QtGui
# Regex adapted from Mark Pilgrim's "Dive Into Python" book
class QHexSpinBox(QDoubleSpinBox):
def __init__(self, parent=None):
super(QHexSpinBox, self).__init__(parent)
self.mode = 'dec'
self.setContextMenuPolicy(Qt.CustomContextMenu);
regex = QRegExp("[x0-9A-Fa-f]{1,8}")
regex.setCaseSensitivity(Qt.CaseInsensitive)
self.hexvalidator = QRegExpValidator(regex, self)
regex = QRegExp("[0-9]{1,10}")
regex.setCaseSensitivity(Qt.CaseInsensitive)
self.decvalidator = QRegExpValidator(regex, self)
regex = QRegExp("[b0-1]{1,64}")
regex.setCaseSensitivity(Qt.CaseInsensitive)
self.binvalidator = QRegExpValidator(regex, self)
self.setRange(1, 999999)
self.connect(self,SIGNAL("customContextMenuRequested(QPoint)"),
self,SLOT("contextMenuRequested(QPoint)"))
@pyqtSlot(QtCore.QPoint)
def contextMenuRequested(self,point):
menu = QtGui.QMenu()
hex = menu.addAction("Hex")
dec = menu.addAction("Dec")
bin = menu.addAction("Bin")
self.connect(hex,SIGNAL("triggered()"),
self,SLOT("hex()"))
self.connect(dec,SIGNAL("triggered()"),
self,SLOT("dec()"))
self.connect(bin,SIGNAL("triggered()"),
self,SLOT("bin()"))
menu.exec_(self.mapToGlobal(point))
@pyqtSlot()
def hex(self):
self.mode = 'hex'
self.setValue(self.value())
@pyqtSlot()
def dec(self):
self.mode = 'dec'
self.setValue(self.value())
@pyqtSlot()
def bin(self):
self.mode = 'bin'
self.setValue(self.value())
def validate(self, text, pos):
if self.mode == 'hex':
return self.hexvalidator.validate(text, pos)
if self.mode == 'dec':
return self.decvalidator.validate(text, pos)
if self.mode == 'bin':
return self.binvalidator.validate(text, pos)
def valueFromText(self, text):
if self.mode == 'hex':
return int(unicode(text), 16)
elif self.mode == 'dec':
return int(unicode(text))
elif self.mode == 'bin':
return int(unicode(text), 2)
def textFromValue(self, value):
value = int(value)
if self.mode == 'hex':
return hex(value)
elif self.mode == 'dec':
return str(value)
elif self.mode =='bin':
return "0b{0:b}".format(value)
Interessante nota "laterale", questo non funziona su 'PySide' si otterrà un' OverflowError: Python int troppo grande per convertire in C lungo' Eccezione –
So che questa è una risposta vecchia, ma sono venuto qui da Google. Ecco la mia soluzione con PySide 1.2.4 basato un po 'fuori della soluzione di Techniquab ma non ha il problema integer overflow:
from PySide import QtCore, QtGui
from numpy import base_repr
from PySide.QtGui import QRegExpValidator
class QBaseSpinBox(QtGui.QAbstractSpinBox):
valueChanged = QtCore.Signal(int)
_value = 0
default_value = 0
base = 10
def __init__(self, parent=None):
self.setRange(None, None)
QtGui.QAbstractSpinBox.__init__(self, parent)
self.set_base(self.base)
self.lineEdit().setValidator(QRegExpValidator(self))
self.default_value = self.value()
self.lineEdit().textChanged.connect(self.textChanged)
self.lineEdit().setContextMenuPolicy(QtCore.Qt.CustomContextMenu);
self.lineEdit().customContextMenuRequested.connect(self.contextMenuRequested)
@QtCore.Slot()
def contextMenuRequested(self, point):
menu = self.lineEdit().createStandardContextMenu() #QtGui.QMenu()
actionDefault = menu.addAction("&Set Default Value of %s" % self.textFromValue(self.default_value),
shortcut=QtCore.Qt.CTRL | QtCore.Qt.Key_D) #QtGui.QKeySequence("Ctrl+D")))
menu.insertSeparator(actionDefault)
actionDefault.triggered.connect(self.menuActionDefault_triggered)
menu.exec_(self.mapToGlobal(point))
@QtCore.Slot()
def menuActionDefault_triggered(self):
self.setValue(self.default_value)
def value(self):
return self._value
def setValue(self, value):
if self.validate(value) == QtGui.QValidator.Invalid:
self.setValue(self._value)
return
changed = False
if self._value != value:
changed = True
self._value = value
self.lineEdit().setText(self.textFromValue(value))
if changed:
self.valueChanged.emit(self._value)
@QtCore.Slot()
def stepBy(self, value):
self.setValue(self._value + value)
QtGui.QAbstractSpinBox.stepBy(self, self._value)
def stepEnabled(self):
return QtGui.QAbstractSpinBox.StepDownEnabled | QtGui.QAbstractSpinBox.StepUpEnabled
@QtCore.Slot()
def textChanged(self, text):
try:
self.setValue(int(text, self.base))
except:
self.setValue(self._value)
def setRange(self, _min, _max):
self.minimum = _min if _min != None else 0
self.maximum = _max if _max != None else 0xFFFFFFFFFFFFFFFF
def validate(self, input):
if not input:
return QtGui.QValidator.Intermediate
try:
try:
value = int(input, self.base)
except TypeError:
value = input
if not (self.minimum <= input <= self.maximum):
raise Exception()
except Exception as ex:
return QtGui.QValidator.Invalid
return QtGui.QValidator.Acceptable
def valueFromText(self, text):
return int(text, self.base)
def textFromValue(self, value):
return base_repr(value, self.base).upper()
def set_default_value(self, value):
self.default_value = int(value)
#self.setValue(self.default_value)
self.set_base(self.base) # Redo the tooltip
def set_base(self, base):
self.base = base
min = self.textFromValue(self.minimum)
max = self.textFromValue(self.maximum)
default = self.textFromValue(self.default_value)
self.lineEdit().setToolTip("Base %d\nRange: %s-%s\nDefault Value: %s" % (self.base, min, max, default))
Se non hanno bisogno di utilizzare tutti i 32 bit si può fare in modo molto semplice come questo:
#pragma once
#include <QSpinBox>
class PaddedSpinBox : public QSpinBox
{
public:
PaddedSpinBox(QWidget *parent = 0) : QSpinBox(parent)
{
}
protected:
QString textFromValue(int value) const override
{
// Pad to the width of maximum().
int width = QString::number(maximum(), displayIntegerBase()).size();
return QString("%1").arg(value, width, displayIntegerBase(), QChar('0')).toUpper();
}
};
Nella forma designer (o qualsiasi altra cosa) poi basta solo impostare:
prefix
:0x
displayIntegerBase
: 16maximum
: 255 (o qualsiasi altra cosa)
Se è necessario utilizzare tutti i 32 bit si dovrà impiegare trucchi colata, o forse solo usare una linea di editing.
- 1. QValidatore per ingresso esadecimale
- 2. Scanf unsigned char in esadecimale
- 3. Conversione di stringa esadecimale in unsigned int issue C++
- 4. comportamento gcc strano con unsigned int
- 5. C++ uint, unsigned int, int
- 6. Trabocco di Unsigned Int
- 7. volatile unsigned int * const
- 8. MSVC++: stranezza con unsigned int e troppopieno
- 9. int alla stringa esadecimale
- 10. unsigned long long int pow
- 11. C# unsigned int valore predefinito
- 12. ingresso JOptionPane a int
- 13. Come formattare unsigned int in un numero esadecimale di 8 cifre?
- 14. differenza tra unsigned short int e unsigned short
- 15. Differenza tra int unsigned e unsigned in C++
- 16. XML xs: int valore esadecimale
- 17. Converti stringa esadecimale in int
- 18. Come leggere unsigned int in Javascript?
- 19. Convertire una stringa esadecimale a un int esadecimale
- 20. stringa esadecimale con conversione int con segno in Ruby
- 21. C++: avviso necessario per: unsigned int i = -1;
- 22. C qual è la forma breve per lungo unsigned int
- 23. La vera differenza tra "int" e "unsigned int"
- 24. Qual è l'identificatore di formato per unsigned short int?
- 25. Compila NSLog con unsigned int e unsigned long su iOS e OSX senza avviso
- 26. Come stampare un long int unsigned con printf in C?
- 27. come convertire ascii in unsigned int
- 28. sprintf e unsigned int array in C
- 29. JNI: conversione di unsigned int in jint
- 30. Stringa esadecimale a 16 bit con firma int in Java
Accetta la tua risposta. – nnb