How to individually customize QTabWidget tabs? - pyqt5

A MRE to customize QTabWidget tabs reads:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QWidget, QAction, QTabWidget,QVBoxLayout
from PyQt5.QtCore import pyqtSlot
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'Tabs tailoring'
self.setWindowTitle(self.title)
self.table_widget = TailoredWidget(self)
self.setCentralWidget(self.table_widget)
self.show()
class TailoredWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = QTabWidget()
self.tabs.setStyleSheet('''QTabBar::tab {font-size: 20pt; color: #00004F; height: 40px; width: 140px;}''')
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tab3 = QWidget()
# Add tabs
self.tabs.addTab(self.tab1,"TAB 1")
self.tabs.addTab(self.tab2,"TAB 2")
self.tabs.addTab(self.tab3,"TAB 3")
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
#pyqtSlot()
def on_click(self):
print("\n")
for currentQTableWidgetItem in self.tableWidget.selectedItems():
print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
This works as expected and allows to play around with the setStyleSheet parameters. However, I'd prefer to be able to customize each tab individually. I tried modifying the initialization of the tabs to:
# Initialize tab screen
self.tabs = QTabWidget()
# self.tabs.setStyleSheet('''QTabBar::tab {font-size: 30pt; color: #00004F; height: 40px; width: 140px;}''')
self.tab1 = QWidget()
self.tab1.setStyleSheet('''QTabBar::tab {font-size: 15pt; color: #55004F; height: 40px; width: 140px;}''')
self.tab2 = QWidget()
self.tab2.setStyleSheet('''QTabBar::tab {font-size: 20pt; color: #AA004F; height: 40px; width: 140px;}''')
self.tab3 = QWidget()
self.tab3.setStyleSheet('''QTabBar::tab {font-size: 25pt; color: #FF004F; height: 40px; width: 140px;}''')
but this doesn't do anything. Is there any way to assign each tab different properties?

Related

Image Super Sampling tool using the Tensorflow library to upscale image in browser

I am unable to generate a super-sampled image and would like some advice.
The HTML, CSS, and JS are below for your review. As you can see, the goal is to enable a webpage visitor to upload a low-resolution image and generate and auto-download an enhanced image. This is meant to be done in the browser without using a database. The image will be stored in the browser, and the user should have a seamless experience.
HTML
<!-- HTML form that allows the user to select and upload an image file -->
<form>
<label for="image">Select an image:</label>
<input type="file" id="image" name="image" accept="image/jpeg, image/png">
<button class="upload-button" onclick="processImage()">Super Sample</button>
</form>
<!-- Canvas element to display the enhanced image -->
<canvas id="canvas"></canvas>
CSS
/* Global styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans- serif;
margin: 0;
background-color: #f3f3f3;
}
/* Styles for the form and canvas elements */
form {
display: flex;
flex-direction: column;
align-items: center;
margin: 50px;
}
label {
color: #333;
font-size: 16px;
}
input[type="file"] {
margin: 10px;
}
button {
margin: 10px;
padding: 10px;
background-color: #333;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
canvas {
border: 1px solid #333;
margin: 10px;
display: block;
}
/* Center the canvas element */
form, canvas {
text-align: center;
}
JS
// Load the TensorFlow.js library
import * as tf from '#tensorflow/tfjs';
// Load the MobileNet model
const model = await tf.loadLayersModel('https://storage.googleapis.com/tfjs- models/tfjs/mobilenet_v1_1.0_224/model.json');
// JavaScript function to process the image and update the download link
async function processImage() {
// Get the selected file from the input element
var file = document.getElementById("image").files[0];
// Check if the file is an image
if (!file.type.match("image.*")) {
alert("Please select an image file");
return;
}
// Create an image element to display the selected image
var image = new Image();
image.src = URL.createObjectURL(file);
// Set the canvas dimensions to the dimensions of the image
var canvas = document.getElementById("canvas");
canvas.width = image.width;
canvas.height = image.height;
// Draw the image on the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, image.width, image.height);
// Convert the canvas to a tensor
var tensor = tf.browser.fromPixels(canvas);
// Resize the tensor to the size expected by the MobileNet model
var resized

How to create a legend from geojson data with react-leaflet

I've got some data represented in my map and I want to create a legend that has the same image of my data and name.
My data are Geojson files.
My map looks like this :
Map without Legend
I want to develop a legend like this :
Map with Legend
This is my code that represents data to the Map :
import React from "react";
import L from "leaflet";
import {
MapContainer,
TileLayer,
GeoJSON,
Marker,
Popup,
LayersControl,
} from "react-leaflet";
import noeud from "./../data/Noeud.json";
import section from "./../data/section.json";
import casier from "./../data/casier.json";
function Macarte() {
const noeud_icon = L.icon({
iconUrl: noeud_image,
iconSize: [10, 10],
});
function casier_style() {
return {
fillColor: "transparent",
color: "red",
};
}
function section_style() {
return {
color: "black",
};
}
return (
<MapContainer className="map" center={[45.7133, 5.52826]} zoom={11}>
<LayersControl position="topright" />
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{noeud.features.map((data_noeud) => (
<Marker
icon={noeud_icon}
position={{
lat: data_noeud.geometry.coordinates[1],
lng: data_noeud.geometry.coordinates[0],
}}
>
<Popup>
<div>
{/*<h1> {"Nom modèle : " + data_noeud.properties.Nom_modele} </h1>*/}
<h1> {"Noeud : " + data_noeud.properties.NOM} </h1>
</div>
</Popup>
</Marker>
))}
<GeoJSON
style={section_style}
data={section.features}
/>
<GeoJSON
style={casier_style}
data={casier.features}
/>
</MapContainer>
);
}
export default Macarte;
Please Help :)
A similar question has been answered here.
Legend component
function Legend({ map }) {
console.log(map);
useEffect(() => {
if (map) {
const legend = L.control({ position: "bottomright" });
legend.onAdd = () => {
const div = L.DomUtil.create("div", "legend");
div.innerHTML =
"<h4>Legend</h4>"
return div;
};
legend.addTo(map);
}
}, [map]); //here add map
return null;
}
in a .css file you can establish rules for the legend then import it into your legend component.
.legend {
padding: 6px 8px;
font: 14px Arial, Helvetica, sans-serif;
background: rgb(255, 255, 255);
line-height: 24px;
color: rgb(0,0,0)
}
.legend h4 {
text-align: center;
font-size: 16px;
margin: 2px 12px 8px;
color: rgb(0,0,0)
}
Then you can simply put the Legend component wherever you want.

How to make react-native-elements Tooltip size dynamic based on its content?

The React Native Elements Tooltip (docs here) requires you to pass in the width and height property for the tooltip, but I want to create a generic tooltip button that can receive any element as its popover prop.
The following example is what I have, but it uses the default size set to the tooltip by the React Native Element library:
import React from 'react'
import { Tooltip } from 'react-native-elements'
import styled from 'styled-components'
const Container = styled.View`
justify-content: center;
align-items: center;
background-color: #aaf;
height: 25px;
width: 25px;
border-radius: 12.5px;
`
const Icon = styled.Text``
export default function TooltipButton({ tooltip }) {
return (
<Tooltip popover={tooltip}>
<Container>
<Icon>?</Icon>
</Container>
</Tooltip>
)
}
When the content is bigger than the default size it looks like this.
I Don't want to have to pass a fixed size as prop to this component, I would like it to have a tooltip size depending on it's content.
After some time trying to figure this out, I managed to do a somewhat autosize tooltip button that receives a content element as a prop (tooltip) and resizes itself based on its content.
The only way I got it to work properly was to set an initial size bigger than the content (500x500) and add more size to it (+30).
import React, { useState } from 'react'
import { Tooltip } from 'react-native-elements'
import styled from 'styled-components'
const Container = styled.View`
justify-content: center;
align-items: center;
background-color: #aaf;
height: 25px;
width: 25px;
border-radius: 12.5px;
`
const Icon = styled.Text``
export default function TooltipButton({ tooltip }) {
const [tooltipSize, setTooltipSize] = useState({ w: 500, h: 500 })
const tooltipClone = React.cloneElement(
tooltip,
{ onLayout: (e) => setTooltipSize({ w: e.nativeEvent.layout.width, h: e.nativeEvent.layout.height }) }
)
return (
<Tooltip
popover={tooltipClone}
width={tooltipSize.w + 30}
height={tooltipSize.h + 30}
>
<Container>
<Icon>?</Icon>
</Container>
</Tooltip>
)
}
End result looks like this.
I guess it's enough to add 20 units to width and height. That's required because the default style applied to the Tooltip component adds a padding of 10, see here.
It seems that using null forces height and width to take as much space as the contents need!
height={null} // using height={null} seems to look good
width={null} // using width={200} seems to look better than null
Source of this hint: ToolTip in react native

PyQt5 Stylesheet For QWidget's Child To Change QWidget

I have a QWidget with a HBoxLayout inside. Inside this HBoxLayout there is a few buttons and a QLineEdit object. Using stylesheets, I would like to make it so that when the QLineEdit is focused, the QWidget gets a blue outline/border.
I have tried:
QSearchWidgetStyleSheet = QWidget {background-color: rgb(27,27,27); border: none; margin: 0px; border-radius: 3px; padding: 0px;}
QLineEdit:focus {border: 3px solid rgb(100,100,100;}
With my QLineEdit stylesheet being:
QLineEditStyleSheet = QLineEdit {color: white; background-color: rgb(255,255,255,0); border: none; height: 32px; border-radius: 3px; margin-left: 3px; margin-right: 3px;}
However, there is no effect on the QWidget when the QLineEdit is focussed. What should I change in order for the QWidget to get the border/outline when the QLineEdit is focused?
QLineEdit:focus applies the style to the QLineEdit, not the QWidget. While child widgets can take up the style sheet of their parent widget, I don't think it works the other way around in general style sheet syntax. Instead you could describe the scenario only considering the QWidget... It should have a border when it is not in focus, and it should not have a border when it is in focus.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Widget(QWidget):
def __init__(self):
super().__init__()
hbox = QHBoxLayout(self)
hbox.addWidget(QPushButton('Push'))
hbox.addWidget(QLineEdit())
self.setAttribute(Qt.WA_StyledBackground, True)
self.setStyleSheet('''
Widget {
border: 3px solid blue;
}
Widget:focus {
border: none;
}''')
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.setFocus()
class Template(QWidget):
def __init__(self):
super().__init__()
grid = QGridLayout(self)
grid.addWidget(Widget(), 0, 0)
self.resize(300, 300)
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = Template()
gui.show()
sys.exit(app.exec_())
Of course if you're open to using other methods, like signals and slots, you could achieve more precisely that functionality.

How to force ECharts charts to a fixed width when printing?

I'm using some echarts in my Vue application with vue-echarts. All charts have :autoresize="true".
My problem is, that if I try to print the page, the width of the charts are set to match the width of the browser. If browser is full screen then some charts get clipped.
CSS:
.echarts {
width: 100%;
min-height: 200px;
}
#media print {
#page { margin: 1cm }
body {
width: 110mm;
height: 297mm;
margin: 25mm 25mm 25mm 25mm;
}
.echarts {width: 600px !important;} /* This does not work! */
}
In the generated DOM there is a container, and inside that another div with the style: position: relative; width: 567px; height: 400px; padding: 0px; margin: 0px; border-width: 0px; cursor: pointer;
Width of the inner container is updated when browser is resized.
Yes, I have faced the same problem. I have also tried before print and after print and call function to redraw the chart but some times its break when Brower gets a zoom out and zoom in.
I say it's not the best solution but it works perfectly.
Solution -
Overwrite the window.print method in mounted.
window.print = function () {
setTimeout(function () {
_print();
}, 500);
};
use flag print_mode for printing.
let self = this;
window.addEventListener('afterprint', function () {
self.print_mode = false;
});
user ref of the chart instance to get base64 data. call getDataURL() to get image data.
chart = echarts.init(chart_dom);
chart_img = chart.getDataURL()
<img v-if="print_mode" class="print-only" :src="chart_img"></img>
so while printing it display image and print and in normal mode, it shows a chart.