def __init__(self, text, duration=None, dayu_type=None, parent=None): super(MToast, self).__init__(parent) self.setWindowFlags( Qt.FramelessWindowHint | Qt.Dialog | Qt.WA_TranslucentBackground | Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_StyledBackground) _icon_lay = QHBoxLayout() _icon_lay.addStretch() if dayu_type == MToast.LoadingType: _icon_lay.addWidget(MLoading(size=dayu_theme.huge, color=dayu_theme.text_color_inverse)) else: _icon_label = MAvatar() _icon_label.set_dayu_size(60) _icon_label.set_dayu_image(MPixmap('{}_line.svg'.format(dayu_type or MToast.InfoType), dayu_theme.text_color_inverse)) _icon_lay.addWidget(_icon_label) _icon_lay.addStretch() _content_label = MLabel() _content_label.setText(text) _content_label.setAlignment(Qt.AlignCenter) _main_lay = QVBoxLayout() _main_lay.setContentsMargins(0, 0, 0, 0) _main_lay.addStretch() _main_lay.addLayout(_icon_lay) _main_lay.addSpacing(10) _main_lay.addWidget(_content_label) _main_lay.addStretch() self.setLayout(_main_lay) self.setFixedSize(QSize(120, 120)) _close_timer = QTimer(self) _close_timer.setSingleShot(True) _close_timer.timeout.connect(self.close) _close_timer.timeout.connect(self.sig_closed) _close_timer.setInterval((duration or self.default_config.get('duration')) * 1000) _ani_timer = QTimer(self) _ani_timer.timeout.connect(self._fade_out) _ani_timer.setInterval((duration or self.default_config.get('duration')) * 1000 - 300) _close_timer.start() _ani_timer.start() self._opacity_ani = QPropertyAnimation() self._opacity_ani.setTargetObject(self) self._opacity_ani.setDuration(300) self._opacity_ani.setEasingCurve(QEasingCurve.OutCubic) self._opacity_ani.setPropertyName('windowOpacity') self._opacity_ani.setStartValue(0.0) self._opacity_ani.setEndValue(0.9) self._get_center_position(parent) self._fade_int()
class MPage(QWidget, MFieldMixin): """ MPage A long list can be divided into several pages by MPage, and only one page will be loaded at a time. """ sig_page_changed = Signal(int, int) def __init__(self, parent=None): super(MPage, self).__init__(parent) self.register_field('page_size_selected', 25) self.register_field('page_size_list', [{ 'label': '25 - Fastest', 'value': 25 }, { 'label': '50 - Fast', 'value': 50 }, { 'label': '75 - Medium', 'value': 75 }, { 'label': '100 - Slow', 'value': 100 }]) self.register_field('total', 0) self.register_field('current_page', 0) self.register_field( 'total_page', lambda: utils.get_total_page( self.field('total'), self.field('page_size_selected'))) self.register_field('total_page_text', lambda: str(self.field('total_page'))) self.register_field( 'display_text', lambda: utils.get_page_display_string( self.field('current_page'), self.field('page_size_selected'), self.field('total'))) self.register_field('can_pre', lambda: self.field('current_page') > 1) self.register_field( 'can_next', lambda: self.field('current_page') < self.field('total_page')) page_setting_menu = MMenu(parent=self) self._display_label = MLabel() self._display_label.setAlignment(Qt.AlignCenter) self._change_page_size_button = MComboBox().small() self._change_page_size_button.setFixedWidth(110) self._change_page_size_button.set_menu(page_setting_menu) self._change_page_size_button.set_formatter( lambda x: u'{} per page'.format(x)) self._change_page_size_button.sig_value_changed.connect( self._emit_page_changed) self._pre_button = MToolButton().icon_only().svg( 'left_fill.svg').small() self._pre_button.clicked.connect( functools.partial(self._slot_change_current_page, -1)) self._next_button = MToolButton().small().icon_only().svg( 'right_fill.svg') self._next_button.clicked.connect( functools.partial(self._slot_change_current_page, 1)) self._current_page_spin_box = MSpinBox() self._current_page_spin_box.setMinimum(1) self._current_page_spin_box.set_dayu_size(dayu_theme.small) self._current_page_spin_box.valueChanged.connect( self._emit_page_changed) self._total_page_label = MLabel() self.bind('page_size_list', page_setting_menu, 'data') self.bind('page_size_selected', page_setting_menu, 'value', signal='sig_value_changed') self.bind('page_size_selected', self._change_page_size_button, 'value', signal='sig_value_changed') self.bind('current_page', self._current_page_spin_box, 'value', signal='valueChanged') self.bind('total_page', self._current_page_spin_box, 'maximum') self.bind('total_page_text', self._total_page_label, 'dayu_text') self.bind('display_text', self._display_label, 'dayu_text') self.bind('can_pre', self._pre_button, 'enabled') self.bind('can_next', self._next_button, 'enabled') main_lay = QHBoxLayout() main_lay.setContentsMargins(0, 0, 0, 0) main_lay.setSpacing(2) main_lay.addStretch() main_lay.addWidget(self._display_label) main_lay.addStretch() main_lay.addWidget(MLabel('|').secondary()) main_lay.addWidget(self._change_page_size_button) main_lay.addWidget(MLabel('|').secondary()) main_lay.addWidget(self._pre_button) main_lay.addWidget(MLabel('Page')) main_lay.addWidget(self._current_page_spin_box) main_lay.addWidget(MLabel('/')) main_lay.addWidget(self._total_page_label) main_lay.addWidget(self._next_button) self.setLayout(main_lay) def set_total(self, value): """Set page component total count.""" self.set_field('total', value) self.set_field('current_page', 1) def _slot_change_current_page(self, offset): self.set_field('current_page', self.field('current_page') + offset) self._emit_page_changed() def set_page_config(self, data_list): """Set page component per page settings.""" self.set_field('page_size_list', [{ 'label': str(data), 'value': data } if isinstance(data, int) else data for data in data_list]) def _emit_page_changed(self): self.sig_page_changed.emit(self.field('page_size_selected'), self.field('current_page'))
def _init_ui(self): main_lay = QVBoxLayout() self.setLayout(main_lay) main_lay.addWidget(MDivider('circle')) lay1 = QHBoxLayout() circle_1 = MProgressCircle(parent=self) circle_1.setFormat(u'%p Days') circle_1.setValue(80) circle_2 = MProgressCircle(parent=self) circle_2.set_dayu_color(dayu_theme.success_color) circle_2.setValue(100) circle_3 = MProgressCircle(parent=self) circle_3.set_dayu_color(dayu_theme.error_color) circle_3.setValue(40) dashboard_1 = MProgressCircle.dashboard(parent=self) dashboard_1.setFormat(u'%p Days') dashboard_1.setValue(80) dashboard_2 = MProgressCircle.dashboard(parent=self) dashboard_2.set_dayu_color(dayu_theme.success_color) dashboard_2.setValue(100) dashboard_3 = MProgressCircle.dashboard(parent=self) dashboard_3.set_dayu_color(dayu_theme.error_color) dashboard_3.setValue(40) lay1.addWidget(circle_1) lay1.addWidget(circle_2) lay1.addWidget(circle_3) dashboard_lay = QHBoxLayout() dashboard_lay.addWidget(dashboard_1) dashboard_lay.addWidget(dashboard_2) dashboard_lay.addWidget(dashboard_3) main_lay.addLayout(lay1) main_lay.addWidget(MDivider('dashboard')) main_lay.addLayout(dashboard_lay) main_lay.addWidget(MDivider('different radius')) circle_4 = MProgressCircle(parent=self) circle_4.set_dayu_width(100) circle_4.setValue(40) circle_5 = MProgressCircle(parent=self) circle_5.setValue(40) circle_6 = MProgressCircle(parent=self) circle_6.set_dayu_width(160) circle_6.setValue(40) lay2 = QHBoxLayout() lay2.addWidget(circle_4) lay2.addWidget(circle_5) lay2.addWidget(circle_6) main_lay.addLayout(lay2) main_lay.addWidget(MDivider('data bind')) self.register_field('percent', 0) self.register_field('color', self.get_color) self.register_field('format', self.get_format) circle = MProgressCircle(parent=self) self.bind('percent', circle, 'value') self.bind('color', circle, 'dayu_color') self.bind('format', circle, 'format') lay3 = QHBoxLayout() button_grp = MPushButtonGroup() button_grp.set_dayu_type(MPushButton.DefaultType) button_grp.set_button_list([ {'text': '+', 'clicked': functools.partial(self.slot_change_percent, 10)}, {'text': '-', 'clicked': functools.partial(self.slot_change_percent, -10)}, ]) lay3.addWidget(circle) lay3.addWidget(button_grp) lay3.addStretch() main_lay.addLayout(lay3) custom_widget = QWidget() custom_layout = QVBoxLayout() custom_layout.setContentsMargins(20, 20, 20, 20) custom_layout.addStretch() custom_widget.setLayout(custom_layout) lab1 = MLabel(text='42,001,776').h3() lab2 = MLabel(text=u'消费人群规模').secondary() lab3 = MLabel(text=u'总占人数 75%').secondary() lab1.setAlignment(Qt.AlignCenter) lab2.setAlignment(Qt.AlignCenter) lab3.setAlignment(Qt.AlignCenter) custom_layout.addWidget(lab1) custom_layout.addWidget(lab2) custom_layout.addWidget(MDivider()) custom_layout.addWidget(lab3) custom_layout.addStretch() custom_circle = MProgressCircle() custom_circle.set_dayu_width(180) custom_circle.setValue(75) custom_circle.set_widget(custom_widget) main_lay.addWidget(MDivider('custom circle')) main_lay.addWidget(custom_circle) main_lay.addStretch()
def _init_ui(self): size_lay = QHBoxLayout() line_edit_l = MLineEdit().large() line_edit_l.setPlaceholderText('large size') line_edit_m = MLineEdit().medium() line_edit_m.setPlaceholderText('default size') line_edit_s = MLineEdit().small() line_edit_s.setPlaceholderText('small size') size_lay.addWidget(line_edit_l) size_lay.addWidget(line_edit_m) size_lay.addWidget(line_edit_s) line_edit_tool_button = MLineEdit(text='MToolButton') line_edit_tool_button.set_prefix_widget(MToolButton().svg('user_line.svg').icon_only()) line_edit_label = MLineEdit(text='MLabel') tool_button = MLabel(text='User').mark().secondary() tool_button.setAlignment(Qt.AlignCenter) tool_button.setFixedWidth(80) line_edit_label.set_prefix_widget(tool_button) line_edit_push_button = MLineEdit(text='MPushButton') push_button = MPushButton(text='Go').primary() push_button.setFixedWidth(40) line_edit_push_button.set_suffix_widget(push_button) search_engine_line_edit = MLineEdit().search_engine().large() search_engine_line_edit.returnPressed.connect(self.slot_search) line_edit_options = MLineEdit() combobox = MComboBox() option_menu = MMenu() option_menu.set_separator('|') option_menu.set_data([r'http://', r'https://']) combobox.set_menu(option_menu) combobox.set_value('http://') combobox.setFixedWidth(90) line_edit_options.set_prefix_widget(combobox) main_lay = QVBoxLayout() main_lay.addWidget(MDivider('different size')) main_lay.addLayout(size_lay) main_lay.addWidget(MDivider('custom prefix and suffix widget')) main_lay.addWidget(line_edit_tool_button) main_lay.addWidget(line_edit_label) main_lay.addWidget(line_edit_push_button) main_lay.addWidget(MDivider('preset')) main_lay.addWidget(MLabel('error')) main_lay.addWidget(MLineEdit(text='waring: file d:/ddd/ccc.jpg not exists.').error()) main_lay.addWidget(MLabel('search')) main_lay.addWidget(MLineEdit().search().small()) main_lay.addWidget(MLabel('search_engine')) main_lay.addWidget(search_engine_line_edit) main_lay.addWidget(MLabel('file')) main_lay.addWidget(MLineEdit().file().small()) main_lay.addWidget(MLabel('folder')) main_lay.addWidget(MLineEdit().folder().small()) main_lay.addWidget(MLabel('MLineEdit.options()')) main_lay.addWidget(line_edit_options) main_lay.addStretch() self.setLayout(main_lay)
class MProgressCircle(QProgressBar): """ MProgressCircle: Display the current progress of an operation flow. When you need to display the completion percentage of an operation. Property: dayu_width: int dayu_color: str """ def __init__(self, dashboard=False, parent=None): super(MProgressCircle, self).__init__(parent) self._main_lay = QHBoxLayout() self._default_label = MLabel().h3() self._default_label.setAlignment(Qt.AlignCenter) self._main_lay.addWidget(self._default_label) self.setLayout(self._main_lay) self._color = None self._width = None self._start_angle = 90 * 16 self._max_delta_angle = 360 * 16 self._height_factor = 1.0 self._width_factor = 1.0 if dashboard: self._start_angle = 225 * 16 self._max_delta_angle = 270 * 16 self._height_factor = (2 + pow(2, 0.5)) / 4 + 0.03 self.set_dayu_width(120) self.set_dayu_color(dayu_theme.primary_color) def set_widget(self, widget): """ Set a custom widget to show on the circle's inner center and replace the default percent label :param widget: QWidget :return: None """ self.setTextVisible(False) self._main_lay.addWidget(widget) def get_dayu_width(self): """ Get current circle fixed width :return: int """ return self._width def set_dayu_width(self, value): """ Set current circle fixed width :param value: int :return: None """ self._width = value self.setFixedSize( QSize(self._width * self._width_factor, self._width * self._height_factor)) def get_dayu_color(self): """ Get current circle foreground color :return: str """ return self._color def set_dayu_color(self, value): """ Set current circle's foreground color :param value: str :return: """ self._color = value self.update() dayu_color = Property(str, get_dayu_color, set_dayu_color) dayu_width = Property(int, get_dayu_width, set_dayu_width) def paintEvent(self, event): """Override QProgressBar's paintEvent.""" if self.text() != self._default_label.text(): self._default_label.setText(self.text()) if self.isTextVisible() != self._default_label.isVisible(): self._default_label.setVisible(self.isTextVisible()) percent = utils.get_percent(self.value(), self.minimum(), self.maximum()) total_width = self.get_dayu_width() pen_width = int(3 * total_width / 50.0) radius = total_width - pen_width - 1 painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) # draw background circle pen_background = QPen() pen_background.setWidth(pen_width) pen_background.setColor(dayu_theme.background_selected_color) pen_background.setCapStyle(Qt.RoundCap) painter.setPen(pen_background) painter.drawArc(pen_width / 2.0 + 1, pen_width / 2.0 + 1, radius, radius, self._start_angle, -self._max_delta_angle) # draw foreground circle pen_foreground = QPen() pen_foreground.setWidth(pen_width) pen_foreground.setColor(self._color) pen_foreground.setCapStyle(Qt.RoundCap) painter.setPen(pen_foreground) painter.drawArc(pen_width / 2.0 + 1, pen_width / 2.0 + 1, radius, radius, self._start_angle, -percent * 0.01 * self._max_delta_angle) painter.end() @classmethod def dashboard(cls, parent=None): """Create a dashboard style MCircle""" return MProgressCircle(dashboard=True, parent=parent)